/*
 * The public part — the brochure.
 *
 * This is the company's own website rebuilt on this project's tokens:
 * `docs/references/steinmann-website.md` is the survey it follows, and every
 * component below appears there under the same name. Where a value here has
 * no obvious reason, the reason is that the site does it that way.
 *
 * The working area shares the colours, the families and the shapes and
 * differs in density — `app.css` runs the sans one weight heavier and one
 * step smaller, because a table of forty rows is read at a different distance
 * from a paragraph of prose.
 *
 * Every value is a token from `tokens.css`. There is no literal colour here,
 * gradients included; `tests/test_design_system.py` reads this file and
 * reports one.
 */

/* The public part is read in sentences and the working area in glances, and
 * that is the whole of the "two densities" this design was accepted on. Here
 * the body is the site's own 1.0375 rem at weight 300, leading 1.75; behind
 * the login it is 15 px at weight 400, leading 1.5.
 *
 * On `.site` rather than on `body`, because `body` is shared: both shells
 * hang off it, and a value set there would drag the working area along.
 *
 * Measured before this: every paragraph of every public page was 15 px at
 * 400 — the application's own figure — because `body` in `custom.css` is the
 * only rule that had ever set one. The difference is a third more air per
 * line, and it is what the reference reads like. */
.site {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-size: var(--text-md);
  font-weight: var(--font-weight-light);
  line-height: var(--text-md-line);
  background-color: var(--color-ground);
}

/* ------------------------------------------------------------------ *
 * The display sizes of the public part.
 *
 * These are the site's own clamps, and they are what the page reads like
 * from across a desk. `custom.css` sets every heading at a fixed step from
 * the text scale, which is right in the working area and half the size here:
 * measured at 1440 px, an `h1` was 36 px against the reference's 74 and an
 * `h2` 24 against 50. The tokens for it existed from the start and nothing
 * used them.
 *
 * On `.site` so that the working area keeps its own, and after the shell
 * rules so that a page hero can still override the top of the scale.
 * ------------------------------------------------------------------ */

/* Every display heading may hyphenate. The clamps are in `rem`, so they
 * follow the reader's font setting — and at 150 per cent the *minimum* of
 * `--display-hero` is 64.8 px, at which "Aussergewöhnliche" is 482 px wide
 * in a 320 px view. The page has `lang="de-ch"`, so the browser breaks it
 * correctly at "Ausser-gewöhnliche" rather than anywhere.
 *
 * `overflow-wrap` is the fallback for the engine that hyphenates nothing: a
 * broken word is ugly, a page that scrolls sideways is unusable. */
.site h1,
.site h2,
.site h3 {
  hyphens: auto;
  /* Only a long word, and never a stub on either side: without the limit a
   * heading broke as "ver-schieben" and "Zuständigkei-ten" on the desktop,
   * where the word had room on the next line. */
  hyphenate-limit-chars: 10 4 4;
  overflow-wrap: break-word;
}

/* `:where()` rather than `.site`, and the zero specificity it carries is the
 * whole point. `.site h2` is one class and one element, which outweighs a
 * bare `.panel__title` -- so every panel heading on a public page was set at
 * `--display-md`, 50 px where the component asks for 20. It showed as soon as
 * a panel stood in a column 320 px wide: "IHRE LIEGENSCHAFT" broke over four
 * lines in the rail of an article, and "Breitenmoser Partner AG" was the
 * largest thing on the contact page.
 *
 * At zero specificity these three are the page's default size for a heading
 * that says nothing else about itself, and any component that names its own
 * size wins without having to fight for it. */
:where(.site) h1 {
  font-size: var(--display-lg);
}

:where(.site) h2 {
  font-size: var(--display-md);
}

:where(.site) h3 {
  font-size: var(--display-sm);
}

/* A label is not prose and is never hyphenated: upper case at this tracking
 * broke as "VER-FASST VON" the moment the rail was narrow. */
.toc__title,
.aside-card__title,
.section-label,
.eyebrow {
  hyphens: none;
}

/* A hero heading is the one step above the rest, and it is set lighter: 300
 * rather than 400, which is what stops five rem of serif reading as a shout. */
.hero h1 {
  font-size: var(--display-hero);
  font-weight: var(--font-weight-light);
}

.page-hero h1 {
  font-size: var(--display-lg);
  font-weight: var(--font-weight-light);
}

/* What is interface rather than prose keeps the interface weight: 400 rather
 * than the 300 of the running text around it. A field or a table cell set at
 * 300 reads as a sentence somebody wrote rather than as a value.
 *
 * `.btn` is deliberately **not** in this list, and it was, and that was a
 * defect: a button in this design is 500, which is the heaviest weight the
 * family owns and the whole of how a button says it is one. `public.css`
 * loads after `custom.css`, so this rule quietly won over `--bs-btn-font-
 * weight` and every button on the public part ran at 400 — measured against
 * the reference, which has 500. Nothing else finds that; it looks like a
 * button either way until the two are put side by side. */
.site .form-control,
.site .form-select,
.site .form-label,
.site table {
  font-weight: var(--font-weight-regular);
}

/* A visitor types into a field at the size of the page around it, not at the
 * working area's caption step: at 13 px beside 16.6 px running text "Bitte
 * wählen" and "name@beispiel.ch" read as fine print (design pass of
 * 2026-10-27). The consent beside its box is read as a sentence, so it takes
 * the size of one. */
.site .form-control,
.site .form-select {
  font-size: var(--text-base);
}

.site .form-check-label {
  font-size: var(--text-base);
  line-height: var(--text-base-line);
  padding-top: calc((var(--target-min) - var(--text-base-line)) / 2);
}

.site-main {
  flex: 1;
}

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

/* The path of a page that has no photograph over it. The header is fixed and
 * 92 px tall, so a container at the very top of the document lies under it:
 * measured at y = 0 on the article and on the search page of the guide, where
 * the path was drawn behind the bar and never seen by anybody. Where a hero
 * follows the path instead, the path goes under the hero -- pushing a hero
 * down by 92 px would take the photograph out from behind the header, which
 * is where the design puts it. */
.crumb-bar {
  padding-top: calc(var(--header-height) + var(--space-6));
}

/* ------------------------------------------------------------------ *
 * The eyebrow — a small capital line in gold with a 44 px rule before it.
 *
 * It appears above nearly every heading on the site and is the single most
 * recognisable thing about the design. `.section-label` is what the templates
 * already call it; `.eyebrow` is the name the survey uses, and both work.
 *
 * The rule is a flex child rather than a border so that it keeps its 44 px
 * whatever the text does, and `flex: none` is what stops it collapsing when
 * the label wraps on a narrow screen.
 * ------------------------------------------------------------------ */

.section-label,
.eyebrow {
  display: flex;
  align-items: center;
  /* The rule and the words go on separate lines rather than off the side
   * when there is no room for both. At 150 per cent type on a 320 px screen
   * "Ausgewählte Objekte" tracked at 0.42em is 259 px wide in a 164 px
   * column, and a flex row that may not wrap takes the page with it. */
  flex-wrap: wrap;
  gap: var(--space-4);
  font-family: var(--font-family-base);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-brand-ink);
}

/* The tracking is the signature of this design and it is also what makes the
 * line unaffordable on a narrow screen at a large type size. Below 30 rem it
 * comes down to the label step — still unmistakably spaced, and 21 per cent
 * narrower. */
@media (max-width: 30rem) {
  .section-label,
  .eyebrow {
    letter-spacing: var(--tracking-label);
    overflow-wrap: break-word;
  }
}

.section-label::before,
.eyebrow::before {
  content: "";
  flex: none;
  width: 44px;
  height: var(--border-hairline);
  background-color: var(--color-brand);
}

.section-label--center,
.eyebrow--center {
  justify-content: center;
}

.section-label--center::after,
.eyebrow--center::after {
  content: "";
  flex: none;
  width: 44px;
  height: var(--border-hairline);
  background-color: var(--color-brand);
}

/* On a dark ground the eyebrow is the brand gold itself — it reaches 7.93:1
 * there and needs no correction. */
.section--accent .section-label,
.section--dark .section-label,
.hero .section-label,
.page-hero .section-label,
.on-dark .section-label {
  color: var(--color-brand-soft);
}

/* ------------------------------------------------------------------ *
 * Header.
 *
 * Fixed, and transparent while the page sits at the top of a hero: the
 * photograph runs underneath it and the wordmark stands on the veil. After
 * 40 px of scroll `app.js` adds `is-scrolled` and it turns solid with the
 * gold hairline under it.
 *
 * Below 960 px it is solid from the start, and that is not a shortcut. A
 * transparent bar over a photograph nobody chose is a bar whose legibility
 * depends on the picture, and on a phone the picture fills the frame. The
 * site makes the same exception at the same width.
 * ------------------------------------------------------------------ */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background-image: var(--veil-header);
  transition: background-color var(--motion-slow) var(--motion-ease),
    box-shadow var(--motion-slow) var(--motion-ease);
}

/* A page without a hero has nothing dark under the bar: white navigation
 * on the paper ground, the active item in gold on cream. */
.site:not(:has(.hero, .page-hero)) .site-header,
.site-header.is-scrolled,
.site-header--solid {
  background-color: var(--black);
  background-image: none;
  box-shadow: 0 var(--border-hairline) 0 var(--color-brand-line);
}

.site-header__inner {
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-gutter);
  min-height: var(--header-height);
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.site-header__spacer {
  flex: 1;
}

/* A bar that sticks has to be affordable. At the reflow condition of WCAG 2.2
 * 1.4.10 — 320 by 256 CSS pixels, which is 400 % zoom on a small laptop — a
 * fixed 92 px bar takes more than a third of the viewport and, because it is
 * fixed, scrolling does not give the space back.
 *
 * So on a viewport short enough for that to bite, the bar scrolls away with
 * the page instead. Nothing is removed and nothing moves: it is the same bar
 * in the same place, and it comes back the moment there is room for it. The
 * condition asks only about height, which is the closest thing to "share of
 * the viewport" that CSS can express. */
@media (max-height: 480px) {
  .site-header {
    position: static;
    background-color: var(--black);
    background-image: none;
  }
}

/* The word mark. Text rather than an image: it is translatable, selectable,
 * readable aloud and it scales with the reader's font setting. The logo file
 * is `static/img/brand/`, and the mark below is what stands where a page has
 * no room for it. */
.wordmark {
  font-family: var(--font-family-base);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-wordmark);
  text-transform: uppercase;
  color: var(--color-on-accent);
  text-decoration: none;
  white-space: nowrap;
}

.wordmark:hover,
.wordmark:focus-visible {
  color: var(--color-brand-soft);
}

/* The word mark is 678 by 128, so its width is 5.3 times its height. Set in
 * `rem` alone it follows the reader's font setting — and at 150 per cent on a
 * 320 px screen that is 318 px of logo in a 320 px bar, which pushed every
 * public page sideways. Measured on all eight of them.
 *
 * It still scales, because a reader who raised the type wants the mark
 * legible too; what it may not do is take the whole bar. Below the cap the
 * height gives way instead, which keeps the mark proportional. */
.wordmark__logo {
  display: block;
  height: 2.5rem;
  width: auto;
  max-width: min(13.25rem, 42vw);
  object-fit: contain;
  object-position: left center;
}

.wordmark__logo--light { display: var(--show-in-light, block); }
.wordmark__logo--dark { display: var(--show-in-dark, none); }

/* Navigation. The underline grows from the left rather than fading in, which
 * costs one pseudo-element and is most of what makes the bar feel made. */
.site-nav ul {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav a {
  position: relative;
  display: block;
  padding-block: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-on-accent);
  text-decoration: none;
}

.site-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0;
  height: var(--border-hairline);
  background-color: var(--color-brand);
  transition: right var(--motion-nav) var(--motion-ease);
}

.site-nav a:hover::after,
.site-nav a:focus-visible::after,
.site-nav a[aria-current="page"]::after {
  right: 0;
}

.site-nav a[aria-current="page"] {
  color: var(--color-brand-soft);
}

/* The handle. A link to the panel's own fragment, so that it opens without
 * JavaScript through `:target` and with it from the Alpine component. */
.site-nav__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--target-primary);
  height: var(--target-primary);
  margin-inline-start: calc(var(--space-2) * -1);
  color: var(--color-on-accent);
  background: none;
  border: none;
}

.site-nav__toggle:hover,
.site-nav__toggle:focus-visible {
  color: var(--color-brand-soft);
}

/* A cross while the panel is open, the three bars otherwise. */
.site-nav__toggle:not([aria-expanded="true"]) .site-nav__icon-close,
.site-nav__toggle[aria-expanded="true"] .site-nav__icon-open {
  display: none;
}

/* ------------------------------------------------------------------ *
 * Hero.
 *
 * A photograph under the three-stop veil, the whole viewport tall. The
 * heading is the serif at weight 300 with one italic gold line in it, which
 * is the site's own construction: `Aussergewöhnliche Immobilien.` in ivory,
 * `Schweizer Vertrauen.` in italic gold underneath.
 *
 * `min-height: 100svh` and not `100vh`: on a phone the browser's own bar
 * counts against `vh` and the scroll hint ends up under it.
 * ------------------------------------------------------------------ */

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background-color: var(--black);
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.hero__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.06);
  animation: hero-settle 9s var(--motion-ease) forwards;
}

@keyframes hero-settle {
  to {
    transform: scale(1);
  }
}

.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--veil-hero);
}

.hero__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  align-self: stretch;
  width: 100%;
  max-width: 62rem;
  margin-inline: auto;
  padding: calc(var(--header-height) + var(--space-8)) var(--space-6)
    var(--space-8);
}

.hero__signet {
  height: 4.625rem;
  width: auto;
  margin: auto auto var(--space-8);
}

.hero__mark {
  display: block;
  margin-bottom: var(--space-6);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-eyebrow-wide);
  text-transform: uppercase;
  color: var(--color-brand-soft);
}

.hero h1 {
  margin-bottom: var(--space-6);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--display-hero);
  font-weight: var(--font-weight-light);
  line-height: 1.08;
  color: var(--color-on-accent);
}

/* The one italic line. It is gold and it is the second half of the sentence,
 * which is why the heading reads as a claim rather than as a label. */
.hero h1 em {
  font-style: italic;
  color: var(--color-brand-soft);
}

.hero__lead {
  max-width: 35rem;
  margin: 0 auto var(--space-12);
  font-size: var(--text-md);
  /* 400 and the full ivory over a photograph: at 300 in the muted ivory the
   * line dissolved against the snow of the mountains behind it (design pass
   * of 2026-10-27). */
  font-weight: var(--font-weight-regular);
  letter-spacing: 0.04em;
  color: var(--color-on-accent);
  text-shadow: 0 1px 12px var(--scrim);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  justify-content: center;
}

/* Text on a photograph. The veil does most of the work; this is what covers
 * the case where the picture is bright exactly where the heading sits. */
.hero__mark,
.hero h1,
.hero__lead,
.hero__scroll,
.page-hero h1,
.page-hero .section-label,
.page-hero__meta {
  text-shadow: 0 2px 26px var(--scrim-deep), 0 1px 5px var(--scrim);
}

.hero__scroll {
  margin-top: auto;
  padding-top: var(--space-10);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-on-accent-muted);
}

.hero__scroll::after {
  content: "";
  width: var(--border-hairline);
  height: 3.25rem;
  background-image: var(--wash-rule);
  animation: scroll-pulse 2.2s ease-in-out infinite;
}

@keyframes scroll-pulse {
  0%,
  100% {
    opacity: 0.35;
  }
  50% {
    opacity: 1;
  }
}

/* A hint to scroll is worth nothing on a screen with no room for it. */
@media (max-height: 700px), (max-width: 700px) {
  .hero__scroll {
    display: none;
  }
}

/* The hero of a subpage: shorter, bottom-aligned, and the photograph does not
 * move. A zoom that runs on every page of a visit stops being an entrance and
 * becomes a tic. */
.page-hero {
  position: relative;
  isolation: isolate;
  min-height: 62vh;
  display: flex;
  align-items: flex-end;
  background-color: var(--black);
}

.page-hero .hero__bg img {
  animation: none;
  transform: none;
}

.page-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--veil-page);
}

.page-hero__inner {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding: calc(var(--header-height) + var(--space-10)) var(--space-gutter)
    var(--space-10);
}

.page-hero h1 {
  margin-top: var(--space-5);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-weight: var(--font-weight-light);
  color: var(--color-on-accent);
}

.page-hero__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-10);
  margin-top: var(--space-5);
  font-size: var(--text-sm);
  letter-spacing: 0.1em;
  color: var(--color-on-accent-muted);
}

.page-hero__price {
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-2xl);
  color: var(--color-brand-soft);
}

/* A page with no photograph of its own still needs its heading to sit
 * somewhere. This is the same block on the paper ground. */
.page-head {
  max-width: var(--page-max);
  margin-inline: auto;
  padding: calc(var(--header-height) + var(--space-12)) var(--space-gutter)
    var(--space-4);
}

.page-head h1 {
  margin-top: var(--space-5);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-weight: var(--font-weight-light);
}

.page-head__lead {
  max-width: var(--prose-max);
  margin-top: var(--space-4);
  font-size: var(--text-md);
  line-height: var(--text-md-line);
  color: var(--color-muted);
}

.page-head__count {
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
  color: var(--color-muted);
}

/* ------------------------------------------------------------------ *
 * Sections. Four grounds, and the ground carries meaning at section level:
 * paper is the page, white is a block that holds objects, and the two dark
 * ones are the blocks that speak for the company rather than about a
 * property.
 * ------------------------------------------------------------------ */

.section {
  padding-block: var(--space-section);
}

/* A section that follows something which has already paid the distance --
 * the path above an article, a heading block above a list. */
.section--flush {
  padding-top: var(--space-6);
}

.section__inner {
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-gutter);
}

.section--tinted {
  background-color: var(--color-surface);
}

.section--solution {
  background-color: var(--color-surface-tinted);
}

/* The panel beside the text of a section: a white card with the site's gold
 * edge along its top, ending where its content ends. As an ivory block on
 * the paper ground it was barely there, and stretched to the height of the
 * text beside it it left a third of itself empty (design pass of
 * 2026-10-27). */
.split > .section--solution {
  align-self: start;
  background-color: var(--color-surface);
  border: var(--border-hairline) solid var(--color-hairline);
  border-top: var(--border-focus) solid var(--color-brand-edge);
  box-shadow: var(--shadow-card);
  padding: var(--space-8);
}

.split > .section--solution h2 { font-size: var(--display-sm); }

.section--accent,
.section--dark {
  background-color: var(--color-band);
  color: var(--text-cool-soft);
}

.section--accent h1,
.section--accent h2,
.section--accent h3,
.section--dark h1,
.section--dark h2,
.section--dark h3 {
  color: var(--color-on-accent);
}

.section--accent .lead,
.section--dark .lead,
.section--accent p,
.section--dark p {
  color: var(--text-cool-soft);
}

/* 54 rem rather than the 48.75 it was. The block is a heading with a lead
 * under it, and at 780 px it was 66 per cent of the 1184 the page has --
 * enough of a difference to read as a column rather than as the top of the
 * section. The lead itself is set in the serif at a size where 864 px is
 * still about seventy characters. */
.section__head {
  max-width: 54rem;
  margin-bottom: var(--space-section-sm);
}

.section__head h2 {
  margin-top: var(--space-5);
}

.section__head p {
  margin-top: var(--space-5);
  color: var(--color-muted);
}

.section__head--center {
  margin-inline: auto;
  text-align: center;
}

/* The lead paragraph is the serif, which is what marks it as language rather
 * than as interface. */
.lead {
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--display-sm);
  line-height: var(--display-line-lead);
  color: var(--color-text);
}

.rule,
.brand-rule {
  height: 0;
  margin: 0;
  border: none;
  border-top: var(--border-hairline) solid var(--color-brand-line);
}

/* ------------------------------------------------------------------ *
 * The property card.
 *
 * White on the paper ground, lifted by the one shadow this design has, with
 * the image scaling inside its own frame on hover. The whole card is a target
 * — the title carries the link and `::after` stretches it over the card, so
 * there is one tab stop and one accessible name rather than three.
 * ------------------------------------------------------------------ */

.property-grid,
.article-grid {
  display: grid;
  /* `auto-fit` rather than `auto-fill`, and the difference is visible
   * whenever the collection is smaller than the row. `auto-fill` keeps the
   * empty tracks it could not fill: one related article sat in a 371 px card
   * with 813 px of paper beside it, measured on the guide. `auto-fit`
   * collapses them, so one card is one card the width of the row. */
  grid-template-columns: repeat(auto-fit, minmax(min(22.5rem, 100%), 1fr));
  gap: var(--space-grid);
  margin: 0;
  padding: 0;
  list-style: none;
}

.property-card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: var(--color-surface);
  box-shadow: var(--shadow-card);
  border: var(--border-hairline) solid var(--color-hairline);
  transition: transform var(--motion-slow) var(--motion-ease),
    box-shadow var(--motion-slow) var(--motion-ease);
}

.property-card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-raised);
}

/* The lift is decoration. Somebody who asked their system for less motion
 * gets the shadow and not the movement. */
@media (prefers-reduced-motion: reduce) {
  .property-card:hover {
    transform: none;
  }
}

.property-card__figure {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 2;
  margin: 0;
  background-color: var(--coal);
}

.property-card__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--motion-image) var(--motion-ease);
}

.property-card:hover .property-card__figure img {
  transform: scale(1.055);
}

/* A property with no released photograph shows the mark rather than a broken
 * frame. Discretion is the default in this trade, and an empty grey box
 * states nothing while a line states a policy. */
.property-card__placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand-soft);
  background-color: var(--coal);
}

.property-card__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: var(--space-6) var(--space-6) var(--space-8);
}

.property-card__place {
  order: -1;
  margin-bottom: var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand-ink);
}

.property-card__title {
  margin: 0;
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-regular);
  line-height: 1.2;
  color: var(--color-heading);
}

.property-card__title a {
  color: inherit;
  text-decoration: none;
}

/* One target over the whole card. The link keeps its own focus ring because
 * the outline is drawn on the anchor and the anchor is the size of the card. */
.property-card__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.property-card__title a:focus-visible {
  outline: none;
}

.property-card:has(.property-card__title a:focus-visible) {
  outline: var(--border-focus) solid var(--color-focus);
  outline-offset: var(--border-focus-offset);
}

.property-card__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-6);
  margin: var(--space-5) 0 0;
  padding: var(--space-5) 0 0;
  border-top: var(--border-hairline) solid var(--color-hairline);
  list-style: none;
  font-size: var(--text-sm);
  color: var(--color-muted);
}

.property-card__ref {
  flex-basis: 100%;
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.property-card__price {
  margin: var(--space-4) 0 0;
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-xl);
  color: var(--color-heading);
}

/* On a card the price stands on the card's floor, so the prices of a row
 * line up whatever the length of the titles above them; a title of three
 * lines put one price 30 px below its neighbour's (design pass of
 * 2026-10-27). The paragraph is there even without a price, so the floor is
 * always held. */
.property-card__body > .property-card__price {
  margin-top: auto;
  padding-top: var(--space-4);
}

/* The flats of a building on its public page: the flat's name in the serif
 * over the row's middle, its price or state at the right and the way into
 * it marked by an arrow. Until the design pass of 2026-10-27 the row was the
 * working area's: a 13 px label hung from the top beside a price set lower,
 * and "Reserviert" in the face of a price. */
.site .unit-list { gap: var(--space-3); }

.site .unit-list a {
  flex-wrap: nowrap;
  gap: var(--space-5);
  padding: var(--space-4) var(--space-6);
  font-size: var(--text-base);
}

.unit-list__name {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-xl);
  line-height: var(--text-xl-line);
}

.site .unit-list .property-card__price {
  flex: none;
  margin: 0;
  font-size: var(--text-lg);
}

.unit-list__state {
  flex: none;
  font-family: var(--font-family-base);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-danger);
}

.unit-list__arrow {
  flex: none;
  font-family: var(--font-family-display);
  color: var(--color-link);
  transition: transform var(--motion-base) var(--motion-ease);
}

.site .unit-list a:hover .unit-list__arrow { transform: translateX(6px); }

@media (prefers-reduced-motion: reduce) {
  .site .unit-list a:hover .unit-list__arrow { transform: none; }
}

@media (max-width: 35rem) {
  .site .unit-list a { flex-wrap: wrap; gap: var(--space-1) var(--space-4); padding-inline: var(--space-4); }
  .unit-list__name { flex-basis: 100%; }
  .unit-list__arrow { margin-inline-start: auto; }
}

/* ------------------------------------------------------------------ *
 * The badge on a photograph — sold, reserved, new.
 * ------------------------------------------------------------------ */

.badge-photo {
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 2;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-pill);
  text-transform: uppercase;
  color: var(--color-brand-soft);
  background-color: var(--black);
  border: var(--border-hairline) solid var(--color-brand-line);
}

.badge-photo--red {
  color: var(--white);
  background-color: var(--red);
  border-color: var(--red);
}

.badge-photo--ivory {
  color: var(--black);
  background-color: var(--ivory);
  border-color: var(--ivory);
}

/* ------------------------------------------------------------------ *
 * The fact bar under a property hero — value over label, the value in the
 * serif and the label in gold capitals.
 * ------------------------------------------------------------------ */

.factbar {
  background-color: var(--ink);
}

.factbar__inner {
  max-width: var(--page-max);
  margin-inline: auto;
  padding: var(--space-6) var(--space-gutter);
  /* Walk of 2026-10-16: a flexible row rather than a grid of equal columns.
   * Seven figures is the usual count for a house and all seven belong on one
   * line at desktop width, but at 7.5rem a column was narrower than
   * "Nettowohnfläche" in capitals and than "Fussbodenheizung" in the serif,
   * and the words were broken ("Nettowohnflä-che", "Kunststoff/P VC"). A
   * figure is now never narrower than its longest word and takes a line of
   * its own before it breaks one. */
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-6);
}

.factbar__inner > * {
  flex: 1 0 7.5rem;
  min-width: min-content;
}

.factbar__value {
  display: block;
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-2xl);
  color: var(--color-on-accent);
  /* A list of kinds (E-129) wraps between its words, never inside one. */
  overflow-wrap: normal;
  hyphens: manual;
}

.factbar__label {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-brand);
  overflow-wrap: normal;
  hyphens: manual;
}

@media (max-width: 43.75rem) {
  .factbar__inner {
    gap: var(--space-3) var(--space-4);
  }

  /* Two figures a line, a long word taking a line of its own. */
  .factbar__inner > * {
    flex-basis: calc(50% - var(--space-4));
  }

  .factbar__value {
    font-size: var(--text-lg);
  }

  .factbar__label {
    letter-spacing: 0.06em;
  }
}

/* ------------------------------------------------------------------ *
 * The bordered panel — a service, a location, an event.
 *
 * A gold border on a near-transparent ground with a diagonal gold wash. On
 * hover the border goes full gold and the panel lifts. It is the dark
 * counterpart of the white card, and the site uses it wherever a block says
 * something about the company rather than about a property.
 * ------------------------------------------------------------------ */

.brand-panel {
  padding: var(--space-10) var(--space-8);
  border: var(--border-hairline) solid var(--color-brand-line-soft);
  background-image: var(--wash-panel);
  transition: border-color var(--motion-slow) var(--motion-ease),
    transform var(--motion-slow) var(--motion-ease);
}

.brand-panel:hover {
  border-color: var(--color-brand);
  transform: translateY(-4px);
}

@media (prefers-reduced-motion: reduce) {
  .brand-panel:hover {
    transform: none;
  }
}

.brand-panel__num {
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-style: italic;
  font-size: var(--text-lg);
  color: var(--color-brand);
}

.brand-panel h3 {
  margin: var(--space-4) 0 var(--space-3);
}

.brand-panel p {
  font-size: var(--text-base);
  margin: 0;
}

.brand-panel-grid {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
  grid-template-columns: repeat(auto-fit, minmax(min(18.75rem, 100%), 1fr));
  gap: var(--space-grid);
}

/* ------------------------------------------------------------------ *
 * The row list — a table that is not a table, for locations and the like.
 *
 * On hover it tints and gains left padding, which reads as the row stepping
 * forward. Below 860 px the description is dropped rather than wrapped: four
 * columns of prose on a phone is four columns of nothing.
 * ------------------------------------------------------------------ */

.row-list {
  border-top: var(--border-hairline) solid var(--color-brand-line-soft);
  margin: 0;
  padding: 0;
  list-style: none;
}

.row-list__row {
  display: grid;
  grid-template-columns: 9.375rem 1.1fr 1.6fr auto;
  align-items: baseline;
  gap: var(--space-5) var(--space-10);
  padding: var(--space-6) var(--space-1);
  border-bottom: var(--border-hairline) solid var(--color-brand-line-soft);
  transition: background-color var(--motion-base) var(--motion-ease),
    padding-left var(--motion-base) var(--motion-ease);
}

.row-list__row:hover {
  background-color: var(--color-brand-wash);
}

.row-list__kind {
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-pill);
  text-transform: uppercase;
  color: var(--color-brand);
}

.row-list__name {
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-2xl);
  line-height: 1.2;
  color: var(--color-on-accent);
}

.row-list__desc {
  font-size: var(--text-base);
  line-height: var(--text-base-line);
  color: var(--color-on-accent-muted);
}

.row-list__state {
  justify-self: end;
  white-space: nowrap;
  padding: var(--space-1-5) var(--space-3);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-pill);
  text-transform: uppercase;
  color: var(--color-brand-soft);
  border: var(--border-hairline) solid var(--color-brand-line);
}

.row-list__state--active {
  color: var(--color-on-brand);
  background-color: var(--color-brand);
  border-color: var(--color-brand);
}

/* Where the four columns stand side by side, they are the list's columns and
 * not each row's own: sized per row by its `auto` state, the descriptions
 * began at three different places down the page. */
@media (min-width: 53.8125rem) {
  /* The country column wide enough for "Vereinigte Arabische Emirate" on
   * two lines rather than three (design pass of 2026-10-27). */
  .row-list {
    display: grid;
    grid-template-columns: 13rem minmax(9rem, 0.6fr) 2fr auto;
    column-gap: var(--space-8);
  }

  .row-list__row {
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
  }
}

@media (max-width: 53.75rem) {
  .row-list__row {
    grid-template-columns: 1fr auto;
  }

  .row-list__kind {
    grid-column: 1 / -1;
  }

  /* Under the name on a telephone rather than gone: the one sentence that
   * says what the place is for (design pass of 2026-10-27). */
  .row-list__desc {
    grid-column: 1 / -1;
    font-size: var(--text-sm);
    line-height: var(--text-sm-line);
  }
}

/* ------------------------------------------------------------------ *
 * The side card on a property page — sticky, white, the price in the serif.
 * ------------------------------------------------------------------ */

.detail-cols {
  display: grid;
  grid-template-columns: 1.7fr 1fr;
  gap: var(--space-section-sm);
  align-items: start;
}

.sidecard {
  position: sticky;
  top: calc(var(--header-height) + var(--space-6));
  padding: var(--space-8);
  background-color: var(--color-surface);
  border: var(--border-hairline) solid var(--color-hairline);
  box-shadow: var(--shadow-card);
}

.sidecard__ref {
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-pill);
  text-transform: uppercase;
  color: var(--color-muted);
}

.sidecard__price {
  margin: var(--space-3) 0 var(--space-6);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-3xl);
  color: var(--color-heading);
}

.sidecard dl {
  margin-bottom: var(--space-6);
}

.sidecard dl > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-2);
  border-bottom: var(--border-hairline) solid var(--color-hairline);
  font-size: var(--text-base);
}

.sidecard dt {
  color: var(--color-muted);
}

.sidecard dd {
  margin: 0;
  text-align: right;
  color: var(--color-heading);
}

.sidecard .btn {
  width: 100%;
  justify-content: center;
}

@media (max-width: 60rem) {
  .detail-cols {
    grid-template-columns: 1fr;
  }

  .sidecard {
    position: static;
  }

  /* Price and enquiry first on a telephone, then the description: in the
   * order of the markup they came 1900 px below the photograph (design pass
   * of 2026-10-27). */
  .detail-cols > .sidecard { order: -1; }
}

/* The highlight list — a gold middot instead of a bullet, on hairlines. */
.checklist {
  margin: var(--space-8) 0;
  padding: 0;
  list-style: none;
}

.checklist li {
  display: flex;
  gap: var(--space-4);
  padding-block: var(--space-3);
  border-bottom: var(--border-hairline) solid var(--color-hairline);
  font-size: var(--text-md);
}

/* A short gold rule in front of each line, the eyebrow's own figure at a
 * quarter of its length, and every property of the working area's tick taken
 * back for it. It was a gold middot, three pixels across and read as a stray
 * dot, behind an indent of 33 px (design pass of 2026-10-27). */
.checklist li {
  align-items: baseline;
  padding-left: 0;
  margin-bottom: 0;
}

.checklist li::before {
  content: "";
  position: static;
  display: block;
  flex: none;
  width: var(--space-4);
  height: var(--border-hairline);
  /* On the middle of the first line, not of the whole entry: an entry of
   * two lines had its rule between them. */
  align-self: flex-start;
  margin-top: calc(var(--text-md-line) / 2);
  background-color: var(--color-brand-edge);
  border-radius: 0;
}

/* ------------------------------------------------------------------ *
 * The filter row — square chips that fill black when they are on.
 * ------------------------------------------------------------------ */

/* The first section of a page without a hero starts below the fixed bar,
 * which on a phone is taller than the section's own top padding. */
.site-main > .section:first-child {
  padding-top: max(var(--space-section), calc(var(--header-height) + var(--space-6)));
}

.filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-section-sm);
}

.filter-row > ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.filter-row__chip {
  padding: var(--space-3) var(--space-6);
  font-family: var(--font-family-base);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  color: var(--color-text);
  background: none;
  border: var(--border-hairline) solid var(--color-border-control);
  transition: color var(--motion-base) var(--motion-ease),
    background-color var(--motion-base) var(--motion-ease),
    border-color var(--motion-base) var(--motion-ease);
}

.filter-row__chip:hover {
  color: var(--color-heading);
  border-color: var(--color-brand-edge);
}

.filter-row__chip[aria-pressed="true"],
.filter-row__chip.is-active {
  color: var(--color-on-primary);
  background-color: var(--color-primary-fill);
  border-color: var(--color-primary-fill);
}

/* The same chip as a link, on the guide's category row. */
a.filter-row__chip {
  display: inline-block;
  text-decoration: none;
}

.filter-row__spacer {
  flex: 1;
}

.filter-row__count {
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
  color: var(--color-muted);
}

/* ------------------------------------------------------------------ *
 * The gallery, and the lightbox it opens.
 *
 * Three fixed layouts rather than one that counts its own columns: one
 * column on a telephone, two on a tablet, three from 62 rem. The rules that
 * close the last row only work when they know how many columns there are,
 * and with `auto-fill` they did not: on a tablet the grid had two columns,
 * the lead and the last picture kept the three-column rules and shrank to
 * 16 and 0 pixels (design pass of 2026-10-28).
 * ------------------------------------------------------------------ */

.gallery {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.gallery a {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background-color: var(--coal);
}

.gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--motion-image) var(--motion-ease);
}

.gallery a:hover img {
  transform: scale(1.05);
}

/* Two columns: the lead across the row, the others in pairs, and a last
 * picture with nobody beside it across the row as well. */
@media (min-width: 43.8125rem) {
  .gallery {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .gallery > li:first-child,
  .gallery > li:nth-child(even):last-child {
    grid-column: 1 / -1;
  }

  .gallery > li:first-child a {
    aspect-ratio: 16 / 9;
  }

  .gallery > li:nth-child(even):last-child:not(:first-child) a {
    aspect-ratio: 3 / 1;
  }
}

/* Three columns: every sixth tile spans two by two, which is what stops a
 * grid of photographs reading as a contact sheet. */
@media (min-width: 62rem) {
  .gallery {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .gallery > li:first-child,
  .gallery > li:nth-child(even):last-child {
    grid-column: auto;
  }

  .gallery > li:first-child a,
  .gallery > li:nth-child(even):last-child:not(:first-child) a {
    aspect-ratio: 4 / 3;
  }

  .gallery > li:nth-child(6n + 1) {
    grid-column: span 2;
    grid-row: span 2;
  }

  /* A last row of one, or a lead with nothing beside it: the whole row. */
  .gallery > li:nth-child(6n + 4):last-child,
  .gallery > li:nth-child(6n + 1):last-child:not(:first-child) {
    grid-column: 1 / -1;
    grid-row: auto;
  }

  .gallery > li:nth-child(6n + 4):last-child a,
  .gallery > li:nth-child(6n + 1):last-child:not(:first-child) a {
    aspect-ratio: 3 / 1;
  }

  /* The lead takes the height of the two rows beside it. At its own 4:3 it
   * ended four pixels above them, which is the row gap it does not span. */
  .gallery:has(> li:nth-child(3)) > li:nth-child(6n + 1):not(:last-child) a {
    aspect-ratio: auto;
    height: 100%;
    contain: size;
  }

  /* A last row of two: the second takes the empty cell, at the height of
   * the one beside it. `contain: size`, so that the picture's own
   * proportions do not raise the row. */
  .gallery > li:nth-child(6n + 5):last-child {
    grid-column: span 2;
  }

  .gallery > li:nth-child(6n + 5):last-child a {
    aspect-ratio: auto;
    height: 100%;
    contain: size;
  }
}

/* Two pictures side by side at the same size, and one across the width it
 * has, at every width from the tablet up. Stated last so that they win
 * over both layouts above. */
@media (min-width: 43.8125rem) {
  .gallery:has(> li:nth-child(2):last-child) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .gallery:has(> li:nth-child(2):last-child) > li {
    grid-column: auto;
    grid-row: auto;
  }

  .gallery:has(> li:nth-child(2):last-child) > li a {
    aspect-ratio: 4 / 3;
  }

  .gallery:has(> li:only-child) {
    grid-template-columns: minmax(0, 1fr);
  }

  .gallery > li:only-child {
    grid-column: auto;
    grid-row: auto;
  }

  .gallery > li:only-child a {
    aspect-ratio: 16 / 9;
  }
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  background-color: var(--color-scrim-deep);
}

.lightbox.is-open {
  display: flex;
}

.lightbox img {
  max-width: 92vw;
  max-height: 86vh;
  object-fit: contain;
}

.lightbox__btn {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--target-primary);
  height: var(--target-primary);
  color: var(--color-on-accent);
  background: none;
  border: var(--border-hairline) solid var(--color-brand-line-soft);
  transition: color var(--motion-base) var(--motion-ease),
    border-color var(--motion-base) var(--motion-ease);
}

.lightbox__btn:hover {
  color: var(--color-brand-soft);
  border-color: var(--color-brand);
}

.lightbox__close {
  top: var(--space-5);
  right: var(--space-5);
}

.lightbox__prev {
  top: 50%;
  left: var(--space-5);
  transform: translateY(-50%);
}

.lightbox__next {
  top: 50%;
  right: var(--space-5);
  transform: translateY(-50%);
}

.lightbox__count {
  position: absolute;
  bottom: var(--space-6);
  left: 50%;
  transform: translateX(-50%);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-pill);
  color: var(--color-on-accent-muted);
}

/* The bar over a list: where the reader is on the left, where they can go
 * next on the right, and a hairline under both. A path on its own was 314 px
 * of ink in a 1184 px band and read as something that had been left over
 * rather than placed. */
.meta-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-6);
  margin-bottom: var(--space-8);
  padding-bottom: var(--space-4);
  border-bottom: var(--border-hairline) solid var(--color-hairline);
}

.meta-bar .breadcrumb {
  margin-bottom: 0;
}

.meta-bar__aside {
  font-size: var(--text-sm);
  color: var(--color-muted);
}

/* ------------------------------------------------------------------ *
 * The long-form shell.
 *
 * Every page that is mostly running text -- the four legal documents, the
 * guide -- is laid out as a text column with a rail beside it rather than as
 * a column of 672 px in a field of 1184. The rail carries the contents of the
 * page and the two or three things a reader of that page needs next, so the
 * width is filled with something rather than held open.
 *
 * The contents themselves are built by `app.js` out of the headings that are
 * actually there. Writing them into each template by hand is a second list to
 * keep in step with the first, and the first is 646 lines long.
 * ------------------------------------------------------------------ */

.longform {
  display: grid;
  /* The same zero as on `.article` above, and for the same reason: a legal
   * document carries tables too. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-grid);
}

.longform .prose,
.longform__body {
  max-width: none;
}

.longform__aside {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

@media (min-width: 62rem) {
  .longform {
    grid-template-columns: minmax(0, 1fr) var(--aside-width);
    align-items: stretch;
  }

  /* The rail comes second in the markup, because the document is what the
   * page is about and what a screen reader should reach first. */
  .longform__aside > :first-child {
    position: sticky;
    top: calc(var(--header-height) + var(--space-5));
  }
}

/* The headings of a long document step down from the page's own: a
 * section heading at the section size, a sub-heading a step under it.
 * The lists take the short gold rule the highlight list has, rather than
 * the browser's black discs (design pass of 2026-10-27). */
.longform__body h2 { font-size: var(--display-section); }

.longform__body h3 {
  font-size: var(--text-2xl);
  line-height: var(--text-2xl-line);
}

:is(.longform__body, .article .prose) ul:not([class]) {
  list-style: none;
  padding-left: 0;
}

:is(.longform__body, .article .prose) ul:not([class]) > li {
  position: relative;
  padding-left: var(--space-8);
}

:is(.longform__body, .article .prose) ul:not([class]) > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.85em;
  width: var(--space-4);
  height: var(--border-hairline);
  background-color: var(--color-brand-edge);
}

/* A text column of 826 px is wider than the 672 it was, so the type grows
 * with it: the measure stays around eighty characters and the page reads
 * larger rather than merely wider. */
@media (min-width: 62rem) {
  .longform__head,
  .longform__body {
    font-size: 1.1rem;
    line-height: 1.7;
  }
}

/* The heading and introduction of a legal document stand in a block of
 * their own above the body (design pass of 2026-10-28), and on a desk the
 * rail beside both, as it stood beside the one block before. */
.longform__head > :last-child { margin-bottom: 0; }

@media (min-width: 62rem) {
  .longform:has(> .longform__head) {
    grid-template-rows: auto 1fr;
    row-gap: var(--space-10);
  }

  .longform__head { grid-column: 1; grid-row: 1; }

  .longform__head ~ .longform__body { grid-column: 1; grid-row: 2; }

  .longform:has(> .longform__head) > .longform__aside {
    grid-column: 2;
    grid-row: 1 / span 2;
  }
}

/* ------------------------------------------------------------------ *
 * Forms on the public pages.
 *
 * The panel fills the column it is given; what holds the measure is the field
 * grid inside it (`.form-grid` in custom.css), which puts two short fields on
 * a line and leaves the long ones the full width. A single 544 px form panel
 * with 640 px of paper beside it was the second largest empty area in this
 * design, and capping the panel was what caused it.
 * ------------------------------------------------------------------ */

.form-panel {
  padding: var(--space-8);
  background-color: var(--color-surface);
  border: var(--border-hairline) solid var(--color-hairline);
  border-top: 2px solid var(--color-brand);
  box-shadow: var(--shadow-card);
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-8);
}

/* The progress rail of a stepped form — two pixels, and the bar is gold. */
.progress-rail {
  position: relative;
  height: 2px;
  margin-bottom: var(--space-10);
  background-color: var(--color-hairline);
}

.progress-rail__bar {
  position: absolute;
  inset: 0 auto 0 0;
  background-color: var(--color-brand);
  transition: width var(--motion-slow) var(--motion-ease);
}

/* ------------------------------------------------------------------ *
 * The guide.
 *
 * Built out of the blocks the public part already has — the card shape of a
 * property, the measure of a form — so that an article does not read as a
 * second product.
 * ------------------------------------------------------------------ */

.article-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--space-8);
  background-color: var(--color-surface);
  border: var(--border-hairline) solid var(--color-hairline);
  border-top: 2px solid var(--color-brand);
  box-shadow: var(--shadow-card);
  transition: transform var(--motion-slow) var(--motion-ease),
    box-shadow var(--motion-slow) var(--motion-ease);
}

.article-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-raised);
}

@media (prefers-reduced-motion: reduce) {
  .article-card:hover {
    transform: none;
  }
}

.article-card__meta {
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand-ink);
}

.article-card__title {
  margin: var(--space-3) 0 0;
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-regular);
  line-height: 1.2;
}

.article-card__title a {
  color: var(--color-heading);
  text-decoration: none;
}

.article-card__title a:hover {
  color: var(--color-brand-ink);
}

.article-card__excerpt {
  flex: 1;
  margin-top: var(--space-3);
  font-size: var(--text-base);
  color: var(--color-muted);
}

.article-card__body {
  display: flex;
  flex: 1;
  flex-direction: column;
}

.article-card__foot {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: var(--border-hairline) solid var(--color-hairline);
  font-size: var(--text-xs);
  color: var(--color-muted);
}

/* The article is a shell rather than a column: the text takes the width that
 * is left over, and the rail beside it carries the contents, the author and
 * the two things a reader does next. The measure is held by the type size
 * instead — see `.article .prose` below, which is set two steps larger than
 * the page around it. A column of 672 px in a field of 1184 was the single
 * largest piece of empty paper in this design. */
.article {
  display: grid;
  /* `minmax(0, 1fr)` and not the implicit `auto` track. An implicit grid
   * track is `auto`, and an `auto` track's floor is the min-content width of
   * what stands in it -- which here is a table set `width: max-content`. On a
   * 390 px telephone the single column was 1018 px and took the page with it;
   * the cap this block replaced had been hiding it. 1.4.10 Reflow.
   * The two-column rule below stands later and in a query, so nothing about
   * the wide view changes. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-grid);
  align-items: start;
}

@media (min-width: 62rem) {
  .article {
    grid-template-columns: minmax(0, 1fr) var(--aside-width);
    align-items: stretch;
  }

  .article__head,
  .article__foot {
    grid-column: 1 / -1;
  }
}

.article__head {
  margin-bottom: var(--space-6);
}

/* 1.2 rem against the 1.0375 of the page. At 826 px the column holds about
 * eighty characters at this size, which is the measure a reading column is
 * meant to have -- the width is spent on larger type rather than on more
 * words a line. */
.article .prose {
  max-width: none;
  font-size: 1.2rem;
  line-height: 1.75;
}

.article .prose table,
.longform__body table {
  min-width: 100%;
  font-size: var(--text-base);
}

.article__byline,
.article__meta {
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  color: var(--color-muted);
}

.article__faq {
  margin-top: var(--space-16);
}

/* The questions under an article, side by side rather than one under the
 * other: eight of them in a single column was a column of closed boxes 640 px
 * long with the width of the page unused beside it. */
.faq-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(26rem, 100%), 1fr));
  gap: var(--space-4);
  align-items: start;
}

.article__foot {
  margin-top: var(--space-12);
}

.article__aside {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* The contents stay in view for the whole article. Everything under them
 * scrolls away as an aside should. */
@media (min-width: 62rem) {
  .article__aside .toc {
    position: sticky;
    top: calc(var(--header-height) + var(--space-5));
  }
}

.aside-card {
  padding: var(--space-6);
  background-color: var(--color-surface);
  border: var(--border-hairline) solid var(--color-hairline);
  border-top: 2px solid var(--color-brand);
}

.aside-card__name {
  margin: 0 0 var(--space-1);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-xl);
  line-height: 1.2;
}

.aside-card__name a {
  color: var(--color-heading);
  text-decoration: none;
}

.aside-card__name a:hover {
  color: var(--color-brand-ink);
}

.aside-card__name {
  margin: 0 0 var(--space-1);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-xl);
  line-height: 1.2;
}

.aside-card__name a {
  color: var(--color-heading);
  text-decoration: none;
}

.aside-card__name a:hover {
  color: var(--color-brand-ink);
}

.aside-card__title {
  margin: 0 0 var(--space-3);
  font-family: var(--font-family-base);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand-ink);
}

.aside-card p:last-child,
.aside-card ul:last-child {
  margin-bottom: 0;
}

.aside-card__list {
  margin: 0;
  padding: 0;
  list-style: none;
  /* The size of the contents list above it: at the small step the other
   * documents read as fine print beside it (design pass of 2026-10-27). */
  font-size: var(--text-base);
}

.aside-card__list a[aria-current="page"] { color: var(--color-brand-ink); }

.aside-card__list li + li {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: var(--border-hairline) solid var(--color-hairline);
}

.aside-card__list a {
  display: block;
  padding-block: var(--space-1);
  color: var(--color-heading);
  text-decoration: none;
}

.aside-card__list a:hover {
  color: var(--color-brand-ink);
}

/* The one dark block of the rail: what the reader is meant to do next. */
.aside-card--accent {
  background-color: var(--black);
  border-color: var(--color-brand-line);
  color: var(--text-cool-soft);
}

.aside-card--accent .aside-card__title {
  color: var(--color-brand);
}

.aside-card--accent p {
  color: var(--text-cool-soft);
}

.author-box {
  margin-top: var(--space-10);
  padding: var(--space-8);
  background-color: var(--color-surface-tinted);
  border-left: 2px solid var(--color-brand);
}

.author-box__name {
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-xl);
  color: var(--color-heading);
}

.toc {
  padding: var(--space-6);
  background-color: var(--color-surface-tinted);
  border-left: 2px solid var(--color-brand);
}

.toc__title {
  /* A label in the interface face, like the card title beside it: as an
   * `h2` it took the serif, and "Inhalt" and "Fragen dazu" were set in two
   * families one above the other. */
  font-family: var(--font-family-base);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand-ink);
}

.toc__list {
  margin: var(--space-4) 0 0;
  padding: 0;
  list-style: none;
}

.toc__list li + li {
  margin-top: var(--space-2);
}

.newsletter {
  padding: var(--space-10) var(--space-8);
  background-color: var(--black);
  border-top: 2px solid var(--color-brand);
  color: var(--text-cool-soft);
}

.newsletter h2,
.newsletter h3 {
  color: var(--color-on-accent);
}

.pagination-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: var(--border-hairline) solid var(--color-hairline);
  font-size: var(--text-sm);
  letter-spacing: 0.06em;
}

/* ------------------------------------------------------------------ *
 * The sign-in pages — the first touch with the product.
 *
 * A split screen: the form on paper to the left, a photograph under a dark
 * veil to the right with the signet on it. On a phone the photograph is a
 * gold band and nothing else, because a hero above a login form is a screen
 * of scrolling before anybody can type.
 * ------------------------------------------------------------------ */

.auth {
  display: grid;
  grid-template-columns: 1fr;
  /* The band is exactly as tall as it is and the form takes the rest. Two
   * `auto` rows share the leftover height of `100svh` between them instead,
   * which measured as 229 px above the card and 107 below it at 390x844 —
   * it reads as generous spacing and is an accident. */
  grid-template-rows: auto 1fr;
  min-height: 100svh;
}

.auth__form {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-12) var(--space-gutter);
  background-color: var(--color-ground);
}

.auth__figure {
  display: none;
  position: relative;
  isolation: isolate;
  background-color: var(--black);
}

/* The photograph, and only the photograph. As a descendant selector this
 * also caught the signet standing on it, which then filled half the screen —
 * `width`/`height` attributes are a hint and lose against any rule. */
.auth__figure > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.auth__signet img {
  width: auto;
  height: 4.875rem;
}

.auth__figure::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--veil-page);
}

.auth__signet {
  position: absolute;
  inset: auto var(--space-12) var(--space-12) var(--space-12);
  z-index: 1;
}

.auth__claim {
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-style: italic;
  font-size: var(--text-2xl);
  color: var(--color-on-accent);
  margin-top: var(--space-5);
}

/* The band that stands in for the photograph on a phone. */
.auth__band {
  height: var(--space-1);
  background-color: var(--color-brand);
}

.auth-card {
  width: 100%;
  max-width: var(--form-max);
  margin-inline: auto;
}

.auth-card__foot {
  margin-top: var(--space-8);
  padding-top: var(--space-6);
  border-top: var(--border-hairline) solid var(--color-hairline);
  font-size: var(--text-sm);
  color: var(--color-muted);
}

.auth-card__foot a svg { margin-inline-end: var(--space-1); }

@media (min-width: 62rem) {
  .auth {
    grid-template-columns: 1fr 1fr;
    /* One row, not two. The band above is `display: none` from here, but
     * `grid-template-rows: auto 1fr` still declares a second row — and the
     * two columns both sit in the first one, which sizes itself to the form.
     * Measured at 1440x900: rows `580px 320px`, so the photograph stopped two
     * thirds of the way down and the last third was bare paper. */
    grid-template-rows: 1fr;
  }

  .auth__figure {
    display: block;
  }

  .auth__band {
    display: none;
  }

  .auth__form {
    padding-inline: var(--space-16);
  }
}

/* ------------------------------------------------------------------ *
 * Footer. Black, four columns, gold column headings, and the Swiss cross
 * drawn rather than fetched — an image for fourteen pixels of flag is a
 * request nobody needs to make.
 * ------------------------------------------------------------------ */

.site-footer {
  background-color: var(--black);
  color: var(--text-cool-soft);
}

.site-footer__inner {
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-gutter);
}

.site-footer__top {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1.2fr;
  gap: var(--space-10);
  padding: var(--space-16) 0 var(--space-12);
}

/* A grid item is `min-width: auto`, which means it never shrinks below its
 * longest unbreakable word. At 150 per cent type on a 320 px screen,
 * "Aussergewöhnliche" is wider than the column, so the column grew and took
 * the page with it — measured at 322 px in a 320 px view on seven pages.
 *
 * `min-width: 0` lets the column shrink; `overflow-wrap` then breaks the word
 * rather than letting it stick out of the column instead. Both are needed:
 * either alone moves the problem rather than solving it. */
.site-footer__top > * {
  min-width: 0;
  overflow-wrap: break-word;
}

.site-footer h2,
.site-footer h3,
.site-footer h4 {
  margin-bottom: var(--space-5);
  font-family: var(--font-family-base);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand);
}

.site-footer ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-footer a {
  display: block;
  padding-block: var(--space-1);
  font-size: var(--text-base);
  color: var(--text-cool-soft);
  text-decoration: none;
}

.site-footer a:hover,
.site-footer a:focus-visible {
  color: var(--color-brand-soft);
}

.site-footer__claim {
  max-width: 18.75rem;
  margin-top: var(--space-5);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-style: italic;
  font-size: var(--text-lg);
  color: var(--text-cool-soft);
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-4) var(--space-10);
  padding: var(--space-6) 0 var(--space-8);
  border-top: var(--border-hairline) solid var(--color-brand-line-soft);
  font-size: var(--text-sm);
  letter-spacing: 0.06em;
}

.site-footer__legal ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
}

.site-footer__legal a {
  display: inline;
}

.swiss-note {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.swiss-note__cross {
  position: relative;
  display: inline-block;
  width: 14px;
  height: 14px;
  background-color: var(--red);
}

.swiss-note__cross::before,
.swiss-note__cross::after {
  content: "";
  position: absolute;
  background-color: var(--white);
}

.swiss-note__cross::before {
  left: 6px;
  top: 2.5px;
  width: 2px;
  height: 9px;
}

.swiss-note__cross::after {
  top: 6px;
  left: 2.5px;
  width: 9px;
  height: 2px;
}

@media (max-width: 60rem) {
  .site-footer__top {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 35rem) {
  .site-footer__top {
    grid-template-columns: 1fr;
    gap: var(--space-8);
  }

  /* Short entries two to a line on a telephone: the footer ran to 1900 px
   * at 390 px, most of it one word per line (design pass of 2026-10-28). */
  .site-footer__top > :nth-child(2) ul,
  .site-footer__top > :nth-child(3) ul,
  .site-footer__top > :nth-child(4) ul {
    columns: 2;
    column-gap: var(--space-6);
  }

  .site-footer__top li {
    break-inside: avoid;
  }

  .site-footer .site-footer__logo {
    height: 6.5rem;
  }
}

/* In the dark set the page above the footer is near-black as well, and the
 * closing band and the footer ran into one another. */
:root[data-theme="dark"] .site-footer {
  border-top: var(--border-hairline) solid var(--color-brand-line-soft);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .site-footer {
    border-top: var(--border-hairline) solid var(--color-brand-line-soft);
  }
}

/* ------------------------------------------------------------------ *
 * Reveal on scroll.
 *
 * `app.js` adds `is-visible` through an IntersectionObserver. The rule that
 * matters is the last one: with reduced motion the element is simply visible,
 * and it is visible whether or not the observer ever runs — an animation that
 * hides content until a script fires is a page that shows nothing when the
 * script does not.
 * ------------------------------------------------------------------ */

/* The attribute is written by `app.js` immediately before the observer is
 * created, and it is the whole safety of this arrangement: without it the
 * rule below does not exist, so a page whose script did not load, or ran and
 * threw, is a page where every block is simply visible.
 *
 * Written the other way round — `.reveal { opacity: 0 }` on its own, with a
 * script that removes it — the same failure hides half the page and nothing
 * reports it, because the markup is all there and the server answered 200.
 * The company's own site is built that way. */
:root[data-reveal="on"] .reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.9s var(--motion-ease),
    transform 0.9s var(--motion-ease);
}

:root[data-reveal="on"] .reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  :root[data-reveal="on"] .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .hero__bg img {
    animation: none;
    transform: none;
  }

  .hero__scroll::after {
    animation: none;
  }
}

/* ------------------------------------------------------------------ *
 * Breakpoints. Every one a `max-width` here, because the public part is laid
 * out for the desk first and folded down — the opposite of the working area,
 * which is a phone first.
 * ------------------------------------------------------------------ */

@media (max-width: 60rem) {
  /* The header is solid from here down: a transparent bar over a photograph
   * nobody chose is a bar whose legibility depends on the picture. */
  .site-header {
    background-color: var(--black);
    background-image: none;
    box-shadow: 0 var(--border-hairline) 0 var(--color-brand-line);
  }

  /* Above the open drawer, which covers the whole screen from here down:
   * the handle is the way out of it again. */
  .site-nav__toggle {
    display: flex;
    position: relative;
    z-index: 121;
  }

  /* The drawer. Full-screen, near-opaque, the entries in the serif at two
   * rem — the site's own mobile menu, which is a page rather than a list. */
  .site-nav {
    position: fixed;
    inset: 0;
    z-index: 120;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* `safe`: a list taller than the screen starts at the top and scrolls,
     * rather than being centred out of reach above and below. On a telephone
     * held sideways (844 by 390) "Immobilien" stood at -58 px and "Anmelden"
     * under the bottom edge (design pass of 2026-10-28). */
    justify-content: safe center;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-block: calc(var(--header-height) + var(--space-4)) var(--space-8);
    background-color: var(--color-scrim-deep);
    /* Over the paper ground the page's own lines still read through the
     * veil at 96 per cent; blurred, they are texture rather than text. */
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    opacity: 0;
    pointer-events: none;
    /* Hidden as well as transparent. `opacity` hides the entries from the
     * eye and from nothing else: until 2026-10-26 the fourth Tab on a
     * telephone landed on "Immobilien" in a menu nobody could see, and six
     * more followed. `visibility` takes them out of the tab order and away
     * from a screen reader. It switches after the fade on closing and at
     * once on opening, so the fade itself is kept. */
    visibility: hidden;
    transition: opacity var(--motion-slow) var(--motion-ease),
                visibility 0s linear var(--motion-slow);
  }

  .site-nav[data-open="true"],
  .site-nav:target {
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
    transition: opacity var(--motion-slow) var(--motion-ease),
                visibility 0s linear 0s;
  }

  .site-nav ul {
    flex-direction: column;
    gap: var(--space-8);
  }

  .site-nav a {
    font-family: var(--font-family-display);
    font-variant-numeric: lining-nums;
    font-size: var(--text-3xl);
    letter-spacing: 0;
    text-transform: none;
    color: var(--color-on-accent);
  }

  .site-nav a::after {
    display: none;
  }

  .site-nav a:hover,
  .site-nav a[aria-current="page"] {
    color: var(--color-brand);
  }

  /* The entries arrive one after the other when the drawer opens. */
  .site-nav li {
    opacity: 0;
    transform: translateY(var(--space-2));
    transition: opacity var(--motion-slow) var(--motion-ease),
                transform var(--motion-slow) var(--motion-ease);
  }

  .site-nav[data-open="true"] li,
  .site-nav:target li {
    opacity: 1;
    transform: none;
  }

  .site-nav[data-open="true"] li:nth-child(2) { transition-delay: 30ms; }
  .site-nav[data-open="true"] li:nth-child(3) { transition-delay: 60ms; }
  .site-nav[data-open="true"] li:nth-child(4) { transition-delay: 90ms; }
  .site-nav[data-open="true"] li:nth-child(5) { transition-delay: 120ms; }
  .site-nav[data-open="true"] li:nth-child(6) { transition-delay: 150ms; }
  .site-nav[data-open="true"] li:nth-child(7) { transition-delay: 180ms; }

  /* The way into the working area is for the office, not for a visitor:
   * set as a label under a hairline rather than as a seventh page. */
  .site-nav .site-nav__app {
    padding-top: var(--space-6);
    border-top: var(--border-hairline) solid var(--color-brand-line);
  }

  .site-nav .site-nav__app a {
    font-family: var(--font-family-base);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--tracking-nav);
    text-transform: uppercase;
    color: var(--color-on-accent-muted);
  }
}

/* A telephone held sideways: the drawer's entries a size down and closer. */
@media (max-width: 60rem) and (max-height: 30rem) {
  /* Two columns, so that all seven fit a screen 390 px high. */
  .site-nav ul {
    display: grid;
    grid-template-columns: repeat(2, auto);
    gap: var(--space-3) var(--space-16);
    text-align: center;
  }

  .site-nav a {
    font-size: var(--text-2xl);
  }

  .site-nav .site-nav__app {
    grid-column: 1 / -1;
    padding-top: var(--space-3);
  }
}

@media (max-width: 60rem) and (prefers-reduced-motion: reduce) {
  .site-nav li {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

@media (max-width: 47.5rem) {
  /* A button that cannot fit its label on one line wraps rather than
   * overflowing, and centres while it does.
   *
   * `min-width: 0` belongs with it: a flex item never shrinks below its
   * content unless told to, so a tracked upper-case label was 292 px wide in
   * a 248 px row and took the page with it. */
  .hero__actions .btn,
  .form-actions .btn {
    flex: 1 1 100%;
    min-width: 0;
    justify-content: center;
    text-align: center;
  }

  /* Every button on the public part, not only the two rows above. The
   * company's own site makes the same exception at the same width, and the
   * reason is the tracking: "Zum Kontaktformular" at 0.22em is 292 px wide,
   * which fits a telephone at 100 per cent type and does not at 150.
   * Measured in the closing band, which is neither a hero nor a form. */
  .site .btn {
    max-width: 100%;
    white-space: normal;
    line-height: 1.45;
  }
}

/* ------------------------------------------------------------------ *
 * The editorial split — text beside a photograph, with the offset frame the
 * company's own "about" page draws behind the picture.
 *
 * The frame is a pseudo-element at negative inset rather than a second image,
 * and it sits *behind* the photograph on `z-index: -1`, which is why the
 * container needs no stacking context of its own.
 * ------------------------------------------------------------------ */

.split-editorial:not(:has(.framed-image)) { align-items: start; }

.split-editorial {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--space-section-sm);
  align-items: center;
}

.framed-image {
  position: relative;
  margin: 0;
}

.framed-image img {
  width: 100%;
  height: auto;
  box-shadow: var(--shadow-card);
}

.framed-image::before {
  content: "";
  position: absolute;
  inset: -22px auto auto -22px;
  width: 60%;
  height: 60%;
  z-index: -1;
  border: var(--border-hairline) solid var(--color-brand-line);
}

@media (max-width: 60rem) {
  .split-editorial {
    grid-template-columns: 1fr;
  }

  /* The offset frame runs off the side of a phone and pushes the page wider
   * than the viewport. It is decoration, so it goes rather than the picture. */
  .framed-image::before {
    display: none;
  }
}

/* ------------------------------------------------------------------ *
 * The values — three statements on a gold rule, and nothing else.
 * ------------------------------------------------------------------ */

.value-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16.25rem, 100%), 1fr));
  gap: var(--space-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.value {
  padding-top: var(--space-6);
  border-top: var(--border-hairline) solid var(--color-brand-line);
}

.value h3 {
  margin-bottom: var(--space-3);
}

.value p {
  margin: 0;
  font-size: var(--text-base);
  color: var(--color-muted);
}

.section--accent .value p,
.section--dark .value p {
  color: var(--text-cool-soft);
}

/* ------------------------------------------------------------------ *
 * The team.
 *
 * A portrait is 3:3.6, slightly desaturated at rest and full on hover, with a
 * gold frame drawing itself inward. The frame is what makes a grid of
 * headshots read as a considered page rather than as a staff directory, and
 * it costs one pseudo-element.
 * ------------------------------------------------------------------ */

.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(15.625rem, 100%), 1fr));
  gap: var(--space-grid);
  margin: 0;
  padding: 0;
  list-style: none;
}

.member {
  text-align: center;
}

.member__photo {
  position: relative;
  aspect-ratio: 3 / 3.6;
  overflow: hidden;
  margin-bottom: var(--space-5);
  background-color: var(--coal);
}

.member__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.88);
  transition: transform var(--motion-image) var(--motion-ease),
    filter var(--motion-slow) var(--motion-ease);
}

.member:hover .member__photo img {
  transform: scale(1.045);
  filter: saturate(1);
}

/* The frame that draws itself inward. `inset` is animatable in every engine
 * this project targets; the border colour carries the fade so that nothing
 * is drawn at all at rest. */
.member__photo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border: var(--border-hairline) solid transparent;
  transition: border-color var(--motion-slow) var(--motion-ease),
    inset var(--motion-slow) var(--motion-ease);
}

.member:hover .member__photo::after {
  inset: 10px;
  border-color: var(--color-brand-line);
}

@media (prefers-reduced-motion: reduce) {
  .member:hover .member__photo img,
  .member:hover .member__photo::after {
    transform: none;
    inset: 0;
  }
}

/* Somebody who joined before the photographer came. */
.member__initials {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  font-size: var(--text-4xl);
  color: var(--color-brand-soft);
}

.member h3 {
  font-size: var(--text-xl);
}

.member__role {
  margin: var(--space-2) 0 0;
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand);
}

.member__role-line {
  display: block;
  line-height: 1.8;
}

/* ------------------------------------------------------------------ *
 * The closing band — a photograph under a heavy wash with one sentence and
 * one button on it.
 * ------------------------------------------------------------------ */

.cta-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  text-align: center;
  background-color: var(--color-band);
}

.cta-band::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--color-scrim);
}

.cta-band .hero__bg img {
  animation: none;
  transform: none;
}

.cta-band__inner {
  max-width: var(--page-max);
  margin-inline: auto;
  padding: var(--space-section) var(--space-gutter);
}

.cta-band h2 {
  max-width: 47.5rem;
  margin: 0 auto var(--space-5);
  color: var(--color-on-accent);
}

.cta-band p {
  max-width: 35rem;
  margin: 0 auto var(--space-10);
  color: var(--color-on-accent-muted);
}

.cta-band p.mb-0 {
  margin-bottom: 0;
}

/* ------------------------------------------------------------------ *
 * Footer additions
 * ------------------------------------------------------------------ */

.site-footer__logo {
  height: 9.375rem;
  width: auto;
}

/* The state over the offices that have not opened, one label per group
 * since the design pass of 2026-10-27. Smaller and quieter than the places
 * it qualifies, because it is a qualification rather than a statement. */
.site-footer__note {
  display: block;
  margin: var(--space-4) 0 var(--space-1);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-wordmark);
  text-transform: uppercase;
  color: var(--color-brand);
  /* Not `nowrap`: tracked at 0.18em the label is wider than the column at
   * 150 per cent type on a 320 px screen. */
}

.site-footer address {
  font-style: normal;
  font-size: var(--text-base);
  line-height: var(--text-md-line);
}

.site-footer li {
  padding-block: var(--space-1);
  font-size: var(--text-base);
}

/* One rhythm in every column: each line carries the distance once, on the
 * link where the line is a link, so that it is part of the target, and on
 * the line where it is a place. Both carried it, and the link lists ran at
 * 45 px a line beside 35 for the places (design pass of 2026-10-27). */
.site-footer li:has(> a) { padding-block: 0; }

.site-footer li > a { padding-block: var(--space-1); }

.site-footer__legal-end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4) var(--space-6);
}

/* The page behind an open lightbox does not scroll. On the body rather than
 * on `html`, because iOS keeps scrolling the root even when it is told not
 * to, and the class is removed again when the dialogue closes. */
.has-modal {
  overflow: hidden;
}

/* The arrow inside a button, which moves on hover. A span rather than a
 * pseudo-element so that a button without one is unaffected, and `aria-hidden`
 * in the markup so it is never read out — an arrow is not a word. */
.btn__arrow {
  display: inline-block;
  margin-left: var(--space-3);
  font-family: var(--font-family-display);
  font-variant-numeric: lining-nums;
  transition: transform var(--motion-base) var(--motion-ease);
}

.btn:hover .btn__arrow {
  transform: translateX(6px);
}

@media (prefers-reduced-motion: reduce) {
  .btn:hover .btn__arrow {
    transform: none;
  }
}

/* ------------------------------------------------------------------ *
 * The outlined button on a photograph.
 *
 * Public only — it exists for the second action of a hero, where a filled
 * button beside the gold one would make neither of them the main action. The
 * ivory edge at 55 per cent is the company's own value; on hover it fills and
 * inverts.
 * ------------------------------------------------------------------ */

.btn-ivory {
  color: var(--color-on-accent);
  background-color: transparent;
  border-color: var(--color-brand-line);
}

.btn-ivory:hover,
.btn-ivory:focus-visible {
  color: var(--color-on-brand);
  background-color: var(--ivory);
  border-color: var(--ivory);
}

/* ------------------------------------------------------------------ *
 * The appearance control in the footer.
 *
 * It sits on the black ground there, so its buttons take the inverse of what
 * `custom.css` gives them on a light one.
 * ------------------------------------------------------------------ */

.site-footer .appearance {
  background-color: transparent;
  border-color: var(--color-brand-line-soft);
}

.site-footer .appearance__button {
  color: var(--color-on-accent-muted);
}

.site-footer .appearance__button:hover {
  color: var(--color-brand-soft);
}

.site-footer .appearance__button[aria-pressed="true"] {
  color: var(--color-on-brand);
  background-color: var(--color-brand);
}

/* ------------------------------------------------------------------ *
 * Corrections measured in the browser rather than reasoned about.
 * Every one of these was a finding of the design matrix — every public page
 * at 360, 768 and 1440 in both themes — and every one is named with what it
 * measured before.
 * ------------------------------------------------------------------ */

/* The header is black in both themes, so everything standing on it takes the
 * inverse of what `custom.css` gives it on a light ground. Measured before:
 * the sign-in link was `--color-heading` on `--black`, which is 1.00:1 in the
 * light theme — the same byte, an invisible control on twenty-six pages.
 *
 * The way into the working area is for the office, not for a visitor, so it
 * is the quietest thing in the header: a muted label behind a hairline that
 * fills only when pointed at. Drawn as a framed button in full ivory it was
 * the loudest control on every public page (design pass of 2026-10-27). */
.site-header .btn-quiet {
  color: var(--color-on-accent-muted);
  border-color: var(--color-brand-line-soft);
}

.site-header .btn-quiet .icon { color: var(--color-brand); }

.site-header .btn-quiet:hover,
.site-header .btn-quiet:focus-visible {
  color: var(--color-on-brand);
  background-color: var(--ivory);
  border-color: var(--ivory);
}

.site-header .btn-quiet:hover .icon,
.site-header .btn-quiet:focus-visible .icon { color: var(--color-on-brand); }

/* The handle collapsed to 18 px because it is a flex child in a row that runs
 * out of space before it. WCAG 2.5.8 asks 24 by 24 of a control, and this one
 * is the only way into the navigation on a telephone. */
.site-nav__toggle {
  flex: none;
}

/* ------------------------------------------------------------------ *
 * Anything on a dark ground.
 *
 * The three dark blocks — the closing band, an accent section, the newsletter
 * — carry forms and prose that `custom.css` styles for a light ground. On the
 * guide that showed as `--color-heading` on `--black`: a consent label at
 * 1.00:1, its field label at 3.65:1 and the link to the privacy policy at
 * 3.85:1.
 *
 * One rule for all three rather than three, because the next dark block
 * would otherwise arrive with the same defect.
 * ------------------------------------------------------------------ */

/* The black main button would vanish on these; it turns light here. The
 * closing band was missing from the list, and its "Zum Kontaktformular" was
 * a black button on the black band in the light theme. */
.newsletter,
.panel--accent,
.aside-card--accent,
.cta-band,
.hero,
.section--accent,
.section--dark {
  --color-primary-fill: var(--ivory);
  --color-on-primary: var(--black);
}

.newsletter,
.section--accent,
.section--dark,
.cta-band {
  --color-heading: var(--text-cool);
  --color-text: var(--text-cool);
  --color-muted: var(--text-cool-soft);
  --color-on-tint: var(--text-cool-soft);
  --color-link: var(--gold-soft);
  --color-link-hover: var(--text-cool);
  --color-danger: var(--red-lifted);
  --color-focus: var(--gold);
  --color-border-control: var(--grey-control-dark);
  --color-hairline: var(--grey-line-dark);
  /* A field on a dark ground keeps a light face: a form the reader types into
   * is the one place the page hands the pen over, and an inverted input is
   * markedly harder to read a long address in. */
  --color-surface: var(--white);
}

/* ------------------------------------------------------------------ *
 * The row list at 360 px.
 *
 * Measured: the country and the state ran to 398 px of a 360 px view. The
 * two-column fold placed a nine-word country beside a state that may not
 * wrap, and neither could give way. At this width the row becomes a stack:
 * the state moves under the name and both may wrap.
 * ------------------------------------------------------------------ */

@media (max-width: 30rem) {
  .row-list__row {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }

  .row-list__state {
    justify-self: start;
    white-space: normal;
  }
}

/* ------------------------------------------------------------------ *
 * A link that stands on its own line is a target, not a word in a sentence,
 * so WCAG 2.5.8's inline exception does not cover it. Measured at 19 and 22
 * pixels of height on three pages.
 *
 * `inline-block` with vertical padding rather than a `min-height`: a height
 * on an inline element does nothing, and the padding grows the hit area
 * without moving the text off its own baseline.
 * ------------------------------------------------------------------ */

:where(.site-main p > a:only-child),
.auth-card__foot a,
.site-footer__legal a {
  display: inline-block;
  padding-block: var(--space-1);
}

/* The way into the application stands twice in the markup and once on the
 * screen: as a button beside the navigation on a desk, as the last entry of
 * the drawer on a telephone. Neither is ever the second copy of the other. */
.site-nav__app {
  display: none;
}

/* Between the tablet and the laptop the six entries and the word mark fill
 * the bar, and the way into the application ran off its right edge at
 * 1024 px (design pass of 2026-10-27). There it is the glyph alone, its word
 * kept for a screen reader. */
@media (min-width: 60.0625rem) and (max-width: 80rem) {
  .site-header__app {
    --bs-btn-padding-x: 0;
    width: var(--control-height);
    min-width: var(--control-height);
  }

  .site-header__app-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

@media (max-width: 60rem) {
  .site-header .btn-quiet {
    display: none;
  }

  .site-nav__app {
    display: block;
  }
}

/* The breadcrumb. Measured at 49 by 19 pixels: a row of targets rather than
 * a sentence, so WCAG 2.5.8's inline exception does not reach it. The padding
 * grows the hit area to 27 px without moving anything, because the row was
 * already taller than its text. */
.breadcrumb-item a {
  display: inline-block;
  padding-block: var(--space-1);
}

/* The locality sketch of a property page (E-02). Drawn in the document
 * rather than fetched: the technical measures this office publishes rule out
 * a third-party map service, so what a tile would have shown is a scale bar,
 * a north arrow and the released area. `landing_pages/maps.py` carries the
 * reasoning. */
.locality {
  margin: 0;
}

/* The sketch or the contact card on its own, at the width either has beside
 * the other rather than across the whole page. */
.locality-single {
  max-width: 36rem;
}

.locality__plan {
  display: block;
  width: 100%;
  max-width: 26rem;
  height: auto;
}

.locality__ground {
  fill: var(--color-surface-tinted);
  stroke: var(--gold-line-soft);
  stroke-width: 1;
}

/* A ring and not a disc. What the drawing says is "somewhere inside this",
 * and a filled shape reads as the outline of a thing. */
.locality__area {
  fill: var(--gold-wash);
  stroke: var(--gold-edge);
  stroke-width: 2;
}

.locality__pin {
  fill: var(--gold-ink);
}

.locality__north line,
.locality__scale line {
  stroke: var(--color-text);
  stroke-width: 2;
}

.locality__north polygon {
  fill: var(--color-text);
}

.locality__north text,
.locality__scale text {
  fill: var(--color-text);
  font-size: 14px;
}

.locality__caption {
  margin-block-start: var(--space-2);
  color: var(--color-muted);
  font-size: var(--text-sm);
}

.contact-person__name {
  margin-block: var(--space-2);
  font-weight: var(--font-weight-medium);
}

/* The language switch of a property page (E-02). A row of codes rather than
 * flag icons: a flag is a country and not a language, and „EN" over a Union
 * Jack is wrong for every reader outside Britain. */
.page-languages__list {
  display: flex;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.page-languages__list [aria-current="true"] {
  color: var(--color-muted);
}

/* E-08: one step of an enquiry form in steps. Without the script every step
 * stands open below the last, which is why a step carries no box of its own. */
.form-step { border: 0; padding: 0; margin: 0 0 var(--space-6); min-width: 0; }
.form-step__legend { font-weight: var(--font-weight-medium); margin-bottom: var(--space-3); }
.form-step__nav { display: flex; gap: var(--space-2); justify-content: space-between;
                  margin-top: var(--space-4); }
.form-step[hidden], .form-step__nav[hidden], .form-actions[hidden] { display: none; }

/* E-141: the two sizes the office may give words of a property text. Relative
 * to the paragraph they stand in, so a larger word in a lead stays in step
 * with the lead. */
.size-large { font-size: 1.25em; line-height: 1.35; }
.size-xlarge { font-size: 1.5em; line-height: 1.3; }

/* The office's preview of a property page (2026-10-19): a band at the foot of
 * the window, where it covers neither the page's own head nor its hero, and
 * stays in sight while the page is read. */
.preview-note {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1050;
  margin: 0;
  background-color: var(--color-surface);
  color: var(--color-text);
  border-color: var(--color-heading);
  box-shadow: 0 -2px 12px var(--shadow-tint-overlay-near);
}
body:has(.preview-note) { padding-bottom: 6rem; }

/* ------------------------------------------------------------------ *
 * The status pages: not found, no access, too many requests, a fault,
 * maintenance.
 *
 * One composition for all six since the design pass of 2026-10-27: centred
 * in the space the header and the footer leave, under the gold eyebrow every
 * other public page carries. They opened with a red pill, which is the
 * signal for "sold" and for an error in a field, and the two that stand
 * without a header were a bare column at the top left of an empty page.
 * The column is a centred box of a few short lines, like the closing band,
 * and so keeps a width of its own.
 * ------------------------------------------------------------------ */

.status-page {
  display: grid;
  align-content: center;
  min-height: min(72vh, 46rem);
}

.status-page .section__inner {
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}

.status-page .section-label { justify-content: center; }

.status-page .lead { margin-inline: auto; }

.status-page p { hyphens: manual; }

.status-page__mark {
  display: block;
  width: auto;
  height: var(--space-12);
  margin: 0 auto var(--space-10);
}

main.status-page { min-height: 100vh; }

/* A heading in an article breaks between words on a wide screen; balanced
 * and hyphenated at once it broke "Grundstück-gewinnsteuer" where a word
 * break would have done (design pass of 2026-10-27). */
@media (min-width: 62rem) {
  .article :is(h2, h3),
  .longform__body :is(h2, h3) { hyphens: manual; }
}

/* On a telephone the closing band and a form card give the content the
 * room their padding took: the gutter, the band's 9 vw and the card's own
 * 32 px left a field 285 px wide (design pass of 2026-10-27). */
@media (max-width: 35rem) {
  .cta-band__inner { padding-block: var(--space-16); }
  .site .form-panel { padding: var(--space-5) var(--space-4); }
}

/* ------------------------------------------------------------------ *
 * Design pass of 2026-10-28 (E-157), public part.
 * ------------------------------------------------------------------ */

/* Headings break between words before they hyphenate, and running text
 * hyphenates only words long enough to bear it: at 390 px an article broke
 * "Grundstückge-winnsteuer" in a heading and every second line of its text. */
.site :is(h1, h2, h3) { hyphenate-limit-chars: 12 5 5; }

.site .prose { hyphenate-limit-chars: 8 4 4; }

/* The two figures beside the place in a property's hero stand again in the
 * fact bar directly under it; on a telephone the hero keeps place and price
 * and the bar carries the figures. */
@media (max-width: 43.75rem) {
  .page-hero__figure { display: none; }
}

/* The keywords of the building over a flat that has none of its own, under
 * a label saying whose they are. */
.checklist__title {
  margin: var(--space-8) 0 0;
  font-family: var(--font-family-base);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-brand-ink);
}

.checklist__title + .checklist { margin-top: var(--space-3); }

/* Pairs in a narrow panel: the term over its value. Side by side, a title of
 * nine words stood four lines deep in a column a third of the panel wide. */
.site .pairs--stacked {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
}

.site .pairs--stacked dd { margin-bottom: var(--space-3); }

/* The contact card beside the locality sketch sits on its middle rather
 * than on its top edge. */
.split:has(> .locality) { align-items: center; }

/* The locations list on a tablet: the state on the line of the name rather
 * than alone under the description. */
@media (min-width: 30.0625rem) and (max-width: 53.75rem) {
  .row-list__name { grid-row: 2; grid-column: 1; }

  .row-list__state { grid-row: 2; grid-column: 2; align-self: center; }
}

/* The team four to a row from 62 rem (eight people were three, three and
 * two at 1024 px), two to a row on a telephone (eight portraits one under
 * the other were 2600 px). The values three to a row from 48 rem. */
@media (min-width: 62rem) {
  .team-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* A role is one or two long words in tracked capitals; in a column of four
 * or two it broke "INTERNATIONALISIERUN-G" wherever the line ended. It
 * hyphenates by the language now, a step tighter below 75 rem. */
.member__role {
  hyphens: auto;
  hyphenate-limit-chars: 10 4 4;
}

@media (max-width: 75rem) {
  .member__role { letter-spacing: var(--tracking-button-app); }
}

@media (max-width: 35rem) {
  .team-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-8) var(--space-4);
  }

  .member h3 { font-size: var(--text-lg); }
}

@media (min-width: 48rem) {
  .value-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* A category name of five words broke inside its pill on a card at 390 and
 * 820 px. Tracked a step tighter on a narrow screen, and cut rather than
 * broken where it still does not fit. */
.article-card__meta .pill,
.article__meta .pill {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 62rem) {
  .article-card__meta .pill,
  .article__meta .pill { letter-spacing: var(--tracking-button-app); }
}

/* A note inside a legal document at the size of the document: at the
 * caption step it was 13 px beside 16.6 px running text. */
.site .longform .notice {
  font-size: var(--text-base);
  line-height: var(--text-base-line);
}

/* The filter chips in one row that scrolls sideways on a telephone and a
 * tablet: six places in three rows of chips stood before the first property
 * at 390 px, and one alone on a second row at 820. */
@media (max-width: 40rem) {
  .filter-row,
  .filter-row > ul {
    flex-wrap: nowrap;
  }

  .filter-row {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    margin-inline: calc(-1 * var(--space-gutter));
    padding: var(--space-1) var(--space-gutter);
    scroll-padding-inline: var(--space-gutter);
  }

  .filter-row::-webkit-scrollbar { display: none; }

  .filter-row__chip {
    flex: none;
    white-space: nowrap;
  }

  .filter-row__spacer { display: none; }

  /* The count stays in sight under the strip: at its end it lay beyond the
   * right edge, and a filter gave no answer one could see. */
  .filter-row__count {
    position: sticky;
    right: 0;
    flex: none;
    white-space: nowrap;
    padding-inline-start: var(--space-3);
    background-color: var(--color-ground);
  }
}

/* The path on a telephone: the step back, on one line, rather than four
 * lines with a separator alone at the start of one. */
@media (max-width: 47.5rem) {
  .site .breadcrumb { flex-wrap: nowrap; }

  .site .breadcrumb-item { display: none; }

  .site .breadcrumb-item:nth-last-child(2) {
    display: flex;
    align-items: baseline;
    min-width: 0;
    padding-left: 0;
  }

  .site .breadcrumb-item:nth-last-child(2)::before {
    content: "\2039";
    float: none;
    padding-right: var(--space-2);
    color: var(--color-muted);
  }

  .site .breadcrumb-item:nth-last-child(2) a {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

/* The contents of a long document first on a tablet and a telephone. In the
 * markup the rail follows the text, so below 62 rem the list of 23 sections
 * stood after the last of them. The rail lets its cards into the page's own
 * grid there, and the contents take the place before the text, in a box of
 * their own height. */
@media (max-width: 61.9375rem) {
  .longform__aside,
  .article__aside { display: contents; }

  .longform__aside > .toc,
  .article__aside > .toc { order: -1; }

  .article__head,
  .longform__head { order: -2; }

}

/* The sign-in pages: a state over a heading stands on a line of its own at
 * its start, as the heading does. Inline, it shared the word mark's line and
 * stood beside it, in the middle of the column. */
.auth-card .section-label {
  display: flex;
  width: fit-content;
}

/* The enquiry bar of a property or flat on a telephone and a tablet in
 * portrait (`data-enquiry-bar`, shown by `app.js` with `is-shown` between
 * the price card and the form). Black, on a gold hairline, the two ways on
 * side by side. */
.enquiry-bar {
  position: fixed;
  inset: auto 0 0;
  z-index: 90;
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-gutter)
    calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  background-color: var(--black);
  border-top: var(--border-hairline) solid var(--color-brand-line);
  --color-primary-fill: var(--ivory);
  --color-on-primary: var(--black);
  transform: translateY(100%);
  visibility: hidden;
  transition: transform var(--motion-slow) var(--motion-ease),
    visibility 0s linear var(--motion-slow);
}

.enquiry-bar.is-shown {
  transform: none;
  visibility: visible;
  transition: transform var(--motion-slow) var(--motion-ease),
    visibility 0s linear 0s;
}

.enquiry-bar .btn {
  flex: 1 1 0;
  min-width: 0;
  justify-content: center;
}

@media (min-width: 60.0625rem) {
  .enquiry-bar { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .enquiry-bar,
  .enquiry-bar.is-shown { transition: none; }
}

/* A token in a table cell is one word: "--tracking-nav" broke after its two
 * hyphens on the style guide at 390 px. */
.site td code { white-space: nowrap; }

/* Between a telephone and a desk the enquiry form keeps the whole width and
 * the two cards beside it go under it: in two equal halves the form stood
 * one field to a line in 365 px. */
@media (min-width: 48rem) and (max-width: 61.99rem) {
  .split.split--wide { grid-template-columns: minmax(0, 1fr); }
}

/* The enquiry bar steps aside while the gallery or the menu lies over the
 * page. */
html:has(.lightbox.is-open) .enquiry-bar,
html:has(#site-nav[data-open="true"]) .enquiry-bar {
  visibility: hidden;
}

/* The preview of a property page is for the office: its note stands where
 * the enquiry bar would, and the bar has nothing to send there. */
body:has(.preview-note) .enquiry-bar { display: none; }
