/* =========================================================================
   WIKO Immobilien — design tokens & base CSS
   Concept: "Cadastral precision" — premium Swiss real-estate. White / near-
   black / deep-ocean-blue (brief-mandated palette). Distinctiveness lives in
   a grotesk+mono type pairing (mono = "cadastral data voice" for prices,
   specs, reference numbers), a roofline signature drawn from WIKO's
   peaked-roof logo (see `.eyebrow::before`), generous Swiss-grid whitespace,
   and hairline rules. Locked design direction — do not improvise the
   palette or fonts; this file is the single source of truth for both.

   Locked primary accent — Deep Ocean Blue: #0A3B54 (--ocean, ~10:1 on
   white). NOT bright/royal blue — it must read as petrol/near-navy.

   Type pairing (all self-hosted under /fonts/, see @font-face below):
     --font-display : Instrument Serif (400 + italic) — headings, hero,
                        page mastheads. ONE weight only, by design: the
                        hierarchy is carried by size and colour, never by
                        bolding — that is what keeps it editorial rather
                        than corporate. Never set font-weight > 400 on it
                        (browsers would synthesise a fake bold).
     --font-body     : Instrument Sans (400, 500, 600) — paragraphs, nav,
                        buttons, forms. Its companion grotesk: shares the
                        skeleton with the serif, so the pairing reads as
                        one voice.
     --font-mono     : Fragment Mono (400) — the "cadastral data voice":
                        eyebrows, reference numbers (WI-1042), spec-table
                        keys, prices and every stat figure. A Helvetica-
                        derived monospace, so it sits inside the Swiss
                        idiom instead of looking like a code terminal.

   Chosen against a measured survey of the brief §1.5 reference sites
   (Livit/Storey/Privera set display type at weight 300–400, body at
   18–20px; Arlewo pairs a serif display with a Swiss grotesk body).
   Brief §4.4 leaves font choice to the design phase but requires "strong
   contrast between headings and content" — hence serif vs grotesk rather
   than two near-identical grotesks.
   ========================================================================= */

/* -------------------------------------------------------------------------
   Fonts — self-hosted, latin + latin-ext (covers ä/ö/ü/ß and CHF). Google
   Fonts serves Instrument Sans as a variable font: requesting several
   static weights returns the *same* file with a different pinned
   `font-weight` per @font-face rule. We mirror that exact technique here —
   one file per subset, several @font-face declarations pointing at it —
   so 8 files cover 3 families / 6 weights / 2 styles (~108 KB total). No
   external requests: every url() below is a same-origin /fonts/ path.
   ------------------------------------------------------------------------- */

@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-serif-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-serif-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-serif-400-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-serif-400-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/instrument-sans-vf-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Fragment Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/fragment-mono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fragment Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/fragment-mono-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Schibsted Grotesk — the interface and data voice (design pass, 10.08.2026).
   Variable across 400–900, self-hosted like every other face here: the CSP is
   `default-src 'self'`, so the Google Fonts import the design used would have
   been blocked and the page would have silently fallen back to system-ui.
   SIL Open Font License 1.1. */
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/schibsted-grotesk-vf-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/schibsted-grotesk-vf-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: italic;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/schibsted-grotesk-vf-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: italic;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/schibsted-grotesk-vf-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* -------------------------------------------------------------------------
   Tokens
   ------------------------------------------------------------------------- */
:root {
  /* Color — light theme only (no dark mode on the public site) */
  --paper: #ffffff;
  --ink: #14181d;
  --ink-soft: #3a424b;
  --stone: #626c77; /* ~4.6:1 on white — do not lighten */
  --mist: #f4f6f8;
  --line: #e2e7ec;
  --ocean: #0a3b54; /* primary accent — links, primary buttons, badges (~10:1 on white) */
  --ocean-deep: #062a3d; /* footer bg, pressed/active button */
  --ocean-tint: #eaf1f5; /* hover/selected fill, ::selection */
  --ocean-bright: #12557a; /* accent on tinted backgrounds (still >=4.5:1 on white) */
  --steel: #8aa9bb; /* soft accent = a light TINT of the brand blue (hero underline, stat marks) — in-family, reads neutral, not a 2nd hue */
  --focus: #12557a;

  /* Typography */
  --font-display: "Instrument Serif", Georgia, "Times New Roman", serif;
  /* Design pass 10.08.2026: two voices, not three. Schibsted Grotesk carries
     both the interface and the data — `--font-mono` keeps its name because
     every call site refers to it, but it is no longer a monospace face and
     numbers are no longer tabular. Instrument Sans and Fragment Mono stay
     shipped as the fallback link in each stack. */
  --font-body: "Schibsted Grotesk", "Instrument Sans", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Schibsted Grotesk", "Instrument Sans", ui-sans-serif, system-ui, sans-serif;

  /* Display sizes run ~10% larger than a grotesk would at the same optical
     weight: Instrument Serif is a single 400 with fine strokes, so it needs
     the extra size to hold the page. Body sits at 18px — the median of the
     reference sites (Livit/Wincasa 20, Storey/Vimova/Arlewo 18). */
  --fs-display: clamp(2.75rem, 1.7rem + 4vw, 4.75rem);
  --fs-h1: clamp(2.25rem, 1.6rem + 2.4vw, 3.4rem);
  --fs-h2: clamp(1.75rem, 1.3rem + 1.5vw, 2.5rem);
  --fs-h3: 1.4375rem;
  --fs-body-lg: 1.25rem;
  --fs-body: 1.125rem;
  --fs-sm: 0.9375rem;
  --fs-eyebrow: 0.75rem;

  /* Spacing (8px base) */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.25rem;
  --s-6: 1.5rem;
  --s-8: 2rem;
  --s-10: 2.5rem;
  --s-12: 3rem;
  --s-16: 4rem;
  --s-20: 5rem;
  --s-24: 6rem;
  --s-32: 8rem;
  --section-y: clamp(4rem, 8vw, 8rem);
  --container: 1200px;
  --gutter: clamp(1.25rem, 5vw, 4rem);

  /* Radii & shadows */
  --r-sm: 4px;
  --r-md: 8px;
  --r-lg: 12px;
  --shadow-sm: 0 1px 2px rgba(20, 24, 29, 0.05);
  --shadow-card: 0 1px 2px rgba(20, 24, 29, 0.04), 0 12px 28px -14px rgba(20, 24, 29, 0.14);

  /* Motion */
  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
  --dur: 200ms;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* -------------------------------------------------------------------------
   Reset & base elements
   ------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

html,
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
picture,
video,
canvas,
svg {
  max-width: 100%;
  height: auto;
  display: block;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--ink);
}

h1 {
  font-size: var(--fs-h1);
  line-height: 1.06;
  letter-spacing: -0.01em;
}

h2 {
  font-size: var(--fs-h2);
  line-height: 1.1;
  letter-spacing: -0.005em;
}

h3,
h4 {
  font-size: var(--fs-h3);
  line-height: 1.25;
  font-weight: 500;
}

p {
  color: var(--ink-soft);
}

a {
  color: var(--ocean);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

a:hover {
  color: var(--ocean-deep);
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

::selection {
  background: var(--ocean-tint);
  color: var(--ink);
}

/* -------------------------------------------------------------------------
   Type-scale utilities — same tokens as the base elements above, exposed as
   classes so any element (e.g. a hero <h1>, an eyebrow <span>) can opt in
   regardless of tag.
   ------------------------------------------------------------------------- */
.fs-display {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-display);
  line-height: 1.02;
  letter-spacing: -0.012em;
}

.fs-h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h1);
  line-height: 1.06;
  letter-spacing: -0.01em;
}

.fs-h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h2);
  line-height: 1.1;
  letter-spacing: -0.005em;
}

.fs-h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h3);
  line-height: 1.25;
}

.fs-body-lg {
  font-size: var(--fs-body-lg);
  line-height: 1.6;
}

.fs-body {
  font-size: var(--fs-body);
  line-height: 1.65;
}

.fs-sm {
  font-size: var(--fs-sm);
  line-height: 1.5;
}

.text-stone {
  color: var(--stone);
}

.text-ink-soft {
  color: var(--ink-soft);
}

.mono {
  font-family: var(--font-mono);
}

.tnum {
  font-feature-settings: "tnum" 1;
  font-variant-numeric: tabular-nums;
}

/* -------------------------------------------------------------------------
   Layout primitives
   ------------------------------------------------------------------------- */
.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-top: var(--section-y);
  padding-bottom: var(--section-y);
}

/* Simple flow spacing (8px-scale vertical rhythm between stacked children) */
.stack > * + * {
  margin-top: var(--s-4);
}
.stack--sm > * + * {
  margin-top: var(--s-2);
}
.stack--lg > * + * {
  margin-top: var(--s-6);
}

.grid {
  display: grid;
  gap: var(--s-6);
}
.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.divider {
  border: none;
  border-top: 1px solid var(--line);
  margin: 0;
}

/* -------------------------------------------------------------------------
   Styleguide-only helper: a color swatch that fills from a design token via
   `data-swatch="--ocean"` instead of an inline style (the CSP's default-src
   'self' fallback governs style-src too, so no `unsafe-inline`). Harmless
   to ship in base.css generally — not page-specific markup, just a mapping
   table from token name to `background`.
   ------------------------------------------------------------------------- */
.swatch[data-swatch="--paper"] {
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.swatch[data-swatch="--ink"] {
  background: var(--ink);
}
.swatch[data-swatch="--ink-soft"] {
  background: var(--ink-soft);
}
.swatch[data-swatch="--stone"] {
  background: var(--stone);
}
.swatch[data-swatch="--mist"] {
  background: var(--mist);
}
.swatch[data-swatch="--line"] {
  background: var(--line);
}
.swatch[data-swatch="--ocean"] {
  background: var(--ocean);
}
.swatch[data-swatch="--ocean-deep"] {
  background: var(--ocean-deep);
}
.swatch[data-swatch="--ocean-tint"] {
  background: var(--ocean-tint);
}
.swatch[data-swatch="--ocean-bright"] {
  background: var(--ocean-bright);
}

/* -------------------------------------------------------------------------
   Eyebrow — mono label with the roofline signature marker.
   The marker is a shallow single-pitch roof (∧), drawn once as an inline
   SVG data-URI, ~14x8px, hairline 1.5px stroke, ocean-colored. It is
   deliberately shallow (not a deep V) to echo the WIKO logo's ridge angle
   without becoming a bold graphic element — the roofline motif is kept to
   this one spot; dividers stay flat elsewhere (see .divider above).
   NOTE: the stroke color below is the literal --ocean hex (#0A3B54) baked
   into the SVG; keep it in sync if that token value ever changes.
   ------------------------------------------------------------------------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ocean);
}

.eyebrow::before {
  content: "";
  flex: none;
  width: 14px;
  height: 8px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 8'%3E%3Cpath d='M1 7 L7 2 L13 7' fill='none' stroke='%230A3B54' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
}

/* -------------------------------------------------------------------------
   Buttons
   ------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.btn--primary {
  background: var(--ocean);
  border-color: var(--ocean);
  color: var(--paper);
}
.btn--primary:hover {
  background: var(--ocean-deep);
  border-color: var(--ocean-deep);
  transform: translateY(-1px);
}
.btn--primary:active {
  background: var(--ocean-deep);
  border-color: var(--ocean-deep);
  transform: translateY(0);
}

.btn--ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--ink);
}
.btn--ghost:hover {
  border-color: var(--ocean);
  color: var(--ocean);
}
.btn--ghost:active {
  border-color: var(--ocean-deep);
  color: var(--ocean-deep);
}

.btn--lg {
  padding: var(--s-4) var(--s-6);
  font-size: var(--fs-body-lg);
}

/* -------------------------------------------------------------------------
   Badges
   ------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 400;
  letter-spacing: 0.02em;
}

.badge--new {
  background: var(--ocean);
  color: var(--paper);
}

.badge--muted {
  background: var(--mist);
  color: var(--stone);
}

/* -------------------------------------------------------------------------
   Cards
   ------------------------------------------------------------------------- */
.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s-6);
  overflow: hidden;
  transition: box-shadow var(--dur) var(--ease);
}

.card:hover {
  box-shadow: var(--shadow-card);
}

.card__media {
  aspect-ratio: 4 / 3;
  margin: calc(var(--s-6) * -1) calc(var(--s-6) * -1) var(--s-6);
  overflow: hidden;
  background: var(--mist);
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* -------------------------------------------------------------------------
   Form controls
   ------------------------------------------------------------------------- */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.label {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}

.input,
.textarea,
.select {
  width: 100%;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink);
  background: var(--paper);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.textarea {
  resize: vertical;
  min-height: 8rem;
}

.input:focus,
.textarea:focus,
.select:focus {
  outline: none;
  border-color: var(--ocean);
  box-shadow: 0 0 0 3px var(--ocean-tint);
}

.input:focus-visible,
.textarea:focus-visible,
.select:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* =========================================================================
   Header — Task 6. Sticky, translucent-white bar (blurred hairline bottom
   border) containing: an optional utility row (reserved for future
   tenant-portal / language links — today only the office phone), the logo,
   the primary nav, and the elevated "Schaden melden" CTA. Below 880px the
   nav becomes a disclosure panel toggled by the hamburger button; the JS
   side (src/public-js/main.ts) owns aria-expanded/focus-trap/Esc, this file
   only owns what's visible and where. 880px is this file's single source of
   truth for the breakpoint — main.ts's matchMedia string must stay in sync
   (see its top-of-file comment).
   ========================================================================= */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  width: 100%;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(140%) blur(8px);
  -webkit-backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--line);
}

.site-header__utility {
  border-bottom: 1px solid var(--line);
  background: var(--mist);
}

.site-header__utility-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding-block: var(--s-1);
}

.site-header__utility-meta {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.04em;
  color: var(--stone);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.site-header__utility-contact {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex: none;
}

.site-header__utility-hours {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.04em;
  color: var(--stone);
  white-space: nowrap;
}

.site-header__utility-link {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.04em;
  color: var(--stone);
  text-decoration: none;
  white-space: nowrap;
}
.site-header__utility-link:hover {
  color: var(--ocean);
}
.site-header__utility-link--phone {
  color: var(--ocean);
}

/* Brand block — the real client logo (roofline mark + wordmark). */
.site-header__brand {
  flex: none;
  display: flex;
  align-items: center;
  text-decoration: none;
  line-height: 1;
}
.site-header__logo-img {
  display: block;
  height: 64px;
  width: auto;
}

.site-header__main-inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6);
  padding-block: var(--s-4);
}

.site-header__logo {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.35rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.site-header__brand:hover .site-header__logo {
  color: var(--ocean);
}
.site-header__logo-accent {
  color: var(--ocean);
}
.site-header__tagline {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 0.6rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ocean-bright);
  white-space: nowrap;
}

/* Utility bar sheds contact detail as width shrinks (keeps phone longest),
   so it never wraps or pushes the layout. */
@media (max-width: 1024px) {
  .site-header__utility-hours,
  .site-header__utility-link:not(.site-header__utility-link--phone) {
    display: none;
  }
}
@media (max-width: 620px) {
  .site-header__utility-meta {
    font-size: 0.62rem;
  }
  .site-header__tagline {
    letter-spacing: 0.2em;
  }
}

.site-header__nav {
  flex: 1 1 auto;
}

.site-header__nav ul {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-8);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-header__nav a {
  position: relative;
  display: inline-block;
  padding-block: var(--s-1);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--fs-body);
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
/* Underline grows from the left on hover (scaleX, GPU-cheap). */
.site-header__nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  background: var(--ocean);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur) var(--ease);
}
.site-header__nav a:hover,
.site-header__nav a:focus-visible {
  color: var(--ocean);
}
.site-header__nav a:hover::after,
.site-header__nav a:focus-visible::after {
  transform: scaleX(1);
}
/* Active page (brief §4.7 "clear navigation structure at all times") —
   the underline stays put and the label holds the accent. */
.site-header__nav a[aria-current="page"] {
  color: var(--ocean);
}
.site-header__nav a[aria-current="page"]::after {
  transform: scaleX(1);
}

/* -- Dienstleistungen disclosure (pure CSS :hover/:focus-within) ------------
   Restrained by design: one hairline panel, no icons, quiet tint hover —
   the Livit/Wincasa dropdown pattern reduced to the monochrome system. */
.site-header__item--sub {
  position: relative;
}
/* Selector carries the extra `.site-header__nav ul` weight deliberately —
   it must out-specify that rule's `display:flex` for this nested ul. */
.site-header__nav ul.site-header__sub {
  display: block;
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, 6px);
  min-width: 230px;
  margin: 0;
  padding: var(--s-2) 0;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.16s var(--ease), transform 0.16s var(--ease), visibility 0s linear 0.16s;
}
/* Invisible hover bridge across the gap between link and panel. */
.site-header__sub::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -12px;
  height: 12px;
}
/* Hover/focus-within is the DESKTOP disclosure. Left unguarded it also fired
   on touch: tapping the mobile toggle puts focus inside the item, `:focus-within`
   matched, and its `translate(-50%)` threw the stacked panel 195px off-screen.
   Below 880px the panel answers to the toggle's `.is-open` class instead. */
@media (min-width: 880px) {
  .site-header__item--sub:hover .site-header__sub,
  .site-header__item--sub:focus-within .site-header__sub {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, 2px);
    transition: opacity 0.16s var(--ease), transform 0.16s var(--ease), visibility 0s;
  }
}
.site-header__sub li {
  border-bottom: none;
}
.site-header__sub a {
  display: block;
  padding: 9px 18px;
  font-size: var(--fs-sm);
  border-bottom: none;
  white-space: nowrap;
}
.site-header__sub a::after {
  content: none;
}
.site-header__sub a:hover,
.site-header__sub a:focus-visible {
  background: var(--ocean-tint);
  color: var(--ocean);
}
.site-header__sub a[aria-current="page"] {
  color: var(--ocean);
  font-weight: 600;
}
.site-header__sub li.site-header__sub-all {
  margin-top: var(--s-1);
  border-top: 1px solid var(--line);
  padding-top: var(--s-1);
}
/* Mobile panel: the services live inline under Dienstleistungen — always
   visible (no hover on touch), quietly indented; the "Alle …" row and the
   chevron are redundant there (the parent link IS the index). */
@media (max-width: 879px) {
  /* Same specificity weight as the desktop panel rule so this wins here. */
  .site-header__nav ul.site-header__sub {
    display: block;
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    min-width: 0;
    padding: 0 0 var(--s-2);
    border: none;
    border-radius: 0;
    box-shadow: none;
    transition: none;
  }
  .site-header__sub::before {
    content: none;
  }
  .site-header__sub a {
    padding: var(--s-2) var(--gutter) var(--s-2) calc(var(--gutter) + var(--s-5));
    color: var(--ink-soft, var(--stone));
  }
  .site-header__sub li.site-header__sub-all {
    display: none;
  }
  /* No underline pseudo-element in the stacked panel (no hover on touch;
     active state is carried by color+weight instead). */
  .site-header__nav a::after {
    content: none;
  }
  .site-header__nav a[aria-current="page"] {
    color: var(--ocean);
    font-weight: 600;
  }
}
.site-header__sub-all a {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--ocean);
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex: none;
}

.site-header__damage-btn {
  white-space: nowrap;
}

.site-header__toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
  cursor: pointer;
  flex: none;
}

.site-header__toggle-bar {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--ink);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}

/* Hamburger -> X while open (aria-expanded is the single source of truth). */
.site-header__toggle[aria-expanded="true"] .site-header__toggle-bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.site-header__toggle[aria-expanded="true"] .site-header__toggle-bar:nth-child(2) {
  opacity: 0;
}
.site-header__toggle[aria-expanded="true"] .site-header__toggle-bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

@media (max-width: 879px) {
  .site-header__nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-card);
    visibility: hidden;
    opacity: 0;
    max-height: 0;
    overflow-y: auto;
    transition: opacity var(--dur) var(--ease), max-height var(--dur) var(--ease);
  }
  /* `.is-open` is toggled by main.ts; `visibility` flips instantly (not
     listed in `transition` above) so closed-panel links leave the a11y
     tree / tab order the moment the class is removed, while opacity/
     max-height still animate the reveal. */
  .site-header__nav.is-open {
    visibility: visible;
    opacity: 1;
    max-height: 80vh;
  }

  .site-header__nav ul {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-block: var(--s-2);
  }
  .site-header__nav li {
    border-bottom: 1px solid var(--line);
  }
  .site-header__nav li:last-child {
    border-bottom: none;
  }
  .site-header__nav a {
    display: block;
    padding: var(--s-4) var(--gutter);
    border-bottom: none;
  }

  .site-header__toggle {
    display: flex;
  }

  /* Two levels, read at a glance.

     The block above already meant to indent the Dienstleistungen children, but
     its `.site-header__sub a` rule sits ABOVE `.site-header__nav a` at the same
     specificity, so the later one won and the children ended up at the parent's
     gutter — eight rows that all looked like siblings. These selectors carry the
     extra class weight to settle it.

     The tie is a hairline down the left of the group rather than more
     whitespace: it says "these belong to the row above" in the same cadastral
     vocabulary the rest of the site uses, and costs no vertical space on a
     screen that has none to spare. */
  .site-header__nav ul.site-header__sub {
    margin-left: var(--gutter);
    border-left: 1px solid var(--line);
  }
  .site-header__nav ul.site-header__sub a {
    padding-left: var(--s-4);
    font-size: var(--fs-sm);
    color: var(--stone);
  }
  /* No rules between the children: the left hairline already groups them and
     the parent li closes the group underneath. Keeping them also doubled the
     closing line, because `:last-child` matches the hidden "Alle
     Dienstleistungen" row rather than the last visible one. */
  .site-header__nav ul.site-header__sub li {
    border-bottom: none;
  }

  /* --- Sub-disclosure -------------------------------------------------- */
  /* The parent row carries the link and the toggle side by side; the panel
     spans the full row underneath and is collapsed until asked for. */
  .site-header__item--sub {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
  }
  .site-header__item--sub > a {
    flex: 1 1 auto;
  }
  .site-header__nav ul.site-header__sub {
    flex: 0 0 100%;
    display: none;
  }
  .site-header__nav ul.site-header__sub.is-open {
    display: block;
  }
  .site-header__sub-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 48px;
    height: 48px;
    margin-right: calc(var(--gutter) - 12px);
    padding: 0;
    border: none;
    background: none;
    color: var(--stone);
    cursor: pointer;
  }
  /* A hairline plus. Expanded, the upright collapses and it reads as a minus —
     the same 1px vocabulary as every other rule on the page, and not a chevron. */
  .site-header__sub-mark {
    position: relative;
    display: block;
    width: 13px;
    height: 13px;
  }
  .site-header__sub-mark::before,
  .site-header__sub-mark::after {
    content: "";
    position: absolute;
    inset: 50% 0 auto 0;
    height: 1px;
    background: currentColor;
  }
  .site-header__sub-mark::after {
    inset: 0 50% auto auto;
    width: 1px;
    height: 100%;
    transform-origin: center;
    transition: transform 0.2s var(--ease);
  }
  .site-header__sub-toggle[aria-expanded="true"] .site-header__sub-mark::after {
    transform: scaleY(0);
  }
  .site-header__sub-toggle:hover,
  .site-header__sub-toggle[aria-expanded="true"] {
    color: var(--ocean);
  }
}

/* Small phones: the wordmark + primary button + hamburger together are
   tight at ~360-390px viewports — trim the two flexible pieces so nothing
   overflows (verified via scripts/shots.mjs at 390px). */
@media (max-width: 479px) {
  .site-header__logo {
    font-size: 1.05rem;
  }
  .site-header__actions {
    gap: var(--s-2);
  }
  .site-header__damage-btn {
    padding: var(--s-2) var(--s-3);
    font-size: var(--fs-sm);
  }
}

/* =========================================================================
   Footer — Task 6. `--ocean-deep` background with light text: `--paper`
   (#FFFFFF) for headings/links (~14.9:1 contrast on #062A3D) and
   `--ocean-tint` (#EAF1F5) for secondary/body text (~13:1) — both far past
   the 4.5:1 floor. Four columns (brand + Angebot + Dienstleistungen +
   Unternehmen) collapse to 2 then 1 for narrower viewports. The roofline
   motif reappears once here, recolored for the dark background, on the
   "Telefonisch erreichbar" label (reuses `.eyebrow`, see below).
   ========================================================================= */
.site-footer {
  background: var(--ocean-deep);
  color: var(--ocean-tint);
}

.site-footer a {
  color: var(--paper);
  text-decoration: none;
}
.site-footer a:hover,
.site-footer a:focus-visible {
  color: var(--ocean-tint);
  text-decoration: underline;
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--s-10);
  padding-block: var(--section-y);
}

@media (max-width: 879px) {
  .site-footer__grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-8) var(--s-6);
  }
  .site-footer__brand {
    grid-column: 1 / -1;
  }
}

@media (max-width: 559px) {
  .site-footer__grid {
    grid-template-columns: 1fr;
  }
}

.site-footer__logo-img {
  display: block;
  height: 88px;
  width: auto;
  margin-bottom: var(--s-4);
}
.site-footer__logo {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.25rem;
  color: var(--paper);
  margin-bottom: var(--s-3);
}

.site-footer__address {
  font-style: normal;
  line-height: 1.6;
  margin-bottom: var(--s-3);
}

.site-footer__contact {
  list-style: none;
  margin: 0 0 var(--s-5);
  padding: 0;
}
.site-footer__contact li + li {
  margin-top: var(--s-1);
}

.site-footer__hours {
  margin-bottom: var(--s-5);
}
.site-footer__hours .eyebrow {
  display: inline-flex;
  margin-bottom: var(--s-2);
  color: var(--ocean-tint);
}
.site-footer__hours .eyebrow::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 8'%3E%3Cpath d='M1 7 L7 2 L13 7' fill='none' stroke='%23EAF1F5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.site-footer__hours ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-footer__hours li + li {
  margin-top: var(--s-1);
}

.site-footer__social {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
}

.site-footer__col h3 {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
  color: var(--paper);
  margin-bottom: var(--s-4);
}
.site-footer__col ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-footer__col li + li {
  margin-top: var(--s-2);
}
.site-footer__col a {
  font-size: var(--fs-sm);
}

.site-footer__bottom {
  border-top: 1px solid var(--ocean);
}
.site-footer__bottom-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-2);
  padding-block: var(--s-4);
}
.site-footer__bottom p {
  margin: 0;
  color: var(--ocean-tint);
}

/* =========================================================================
   Homepage — Task 7. Section-background utilities + the nine homepage
   sections (plan §6 formula: hero -> intro -> quick tiles -> services ->
   featured -> stats -> team -> partners -> contact band). Everything below
   builds on Task 5's tokens/components (.section/.container/.card/.btn/
   .badge/.eyebrow/.grid) — no new colors, no inline styles.
   ========================================================================= */

/* -- section background utilities (composable with .section) ------------- */
.section--mist {
  background: var(--mist);
}
.section--ocean-tint {
  background: var(--ocean-tint);
}
.section--ocean-deep {
  background: var(--ocean-deep);
  color: var(--ocean-tint);
}
/* Base h2-h4/.eyebrow hardcode --ink/--ocean; every dark section needs its
   own override (specificity, not just inheritance) — reused by the hero's
   dark scrim and any future --ocean-deep section. */
.section--ocean-deep h2,
.section--ocean-deep h3 {
  color: var(--paper);
}
.section--ocean-deep .eyebrow {
  color: var(--paper);
}
.section--ocean-deep .eyebrow::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 8'%3E%3Cpath d='M1 7 L7 2 L13 7' fill='none' stroke='%23EAF1F5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* -- section heading (eyebrow + h2[, right-aligned CTA link]) ------------- */
.section-head {
  margin-bottom: var(--s-10);
  max-width: 42rem;
}
/* Big editorial section title (mockup scale) — h2s inside section heads and
   the about/contact bands step up from the base --fs-h2. */
.section-title {
  font-size: clamp(1.9rem, 1.4rem + 2vw, 2.9rem);
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--ocean-deep);
}
/* Mono index inside a numbered eyebrow — the homepage's cadastral "01–05". */
.eyebrow__idx {
  font-weight: 600;
  color: var(--ocean);
  margin-right: var(--s-1);
}
.section-head--split {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-6);
  max-width: none;
}

/* -- 1. Hero — editorial split (Cadastral Editorial) ----------------------
   Oversized headline on the left, a framed property photo on the right over
   a hairline cadastral grid. The section's height is driven by content; the
   photo carries a fixed CSS height + width/height attrs (Home.tsx) so its
   box is stable before load — zero CLS. */
.hero {
  position: relative;
  overflow: hidden;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
/* Faint survey/cadastral grid, radial-masked so it fades toward the copy. */
.hero__grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(120% 100% at 72% 0%, #000 30%, transparent 78%);
  mask-image: radial-gradient(120% 100% at 72% 0%, #000 30%, transparent 78%);
}
.hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--s-12);
  align-items: center;
  padding-block: var(--s-16);
}
.hero__content {
  max-width: 34rem;
}
.hero__title {
  margin-top: var(--s-4);
  font-size: clamp(2.9rem, 5.6vw, 5.1rem);
  line-height: 1;
  letter-spacing: -0.014em;
  color: var(--ocean-deep);
}
/* The one accent inside the monochrome system: the closing word of the
   headline turns to an Instrument Serif italic in brand blue. It is the only
   italic on the site — spend the boldness once. */
.hero__title-accent {
  font-style: italic;
  color: var(--ocean);
  position: relative;
}
/* Positioning line under the H1 (round-3 brief): part of the headline lockup,
   not a subtitle — it echoes the H1's italic serif accent so the two read as
   one statement, then the grotesk subtitle states the concrete offer below. */
.hero__positioning {
  margin-top: var(--s-4);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.15rem, 1rem + 0.9vw, 1.6rem);
  line-height: 1.2;
  color: var(--ocean-bright);
  max-width: 34ch;
}
/* Trust stats row under the CTAs (mockup element restored). */
.hero__trust {
  display: flex;
  gap: var(--s-8);
  margin-top: var(--s-8);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}
.hero__trust-item {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.hero__trust-item b {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ocean-deep);
  line-height: 1;
}
.hero__trust-item span {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute, var(--stone));
}
/* One-time entrance: copy rises, photo settles — killed under reduced motion
   (the global reduced-motion rule zeroes animation durations). */
@keyframes hero-rise {
  from {
    opacity: 0;
    transform: translateY(22px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes hero-settle {
  from {
    opacity: 0;
    transform: scale(1.025);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.hero__content {
  animation: hero-rise 0.7s var(--ease) both;
}
.hero__media {
  animation: hero-settle 0.9s var(--ease) both;
}
.hero__subtitle {
  margin-top: var(--s-5);
  max-width: 34ch;
  font-size: var(--fs-body-lg);
  color: var(--ink-soft);
}
.hero__actions {
  margin-top: var(--s-8);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
}
.hero__media {
  position: relative;
}
.hero__media img {
  display: block;
  width: 100%;
  height: min(58vh, 540px);
  object-fit: cover;
  border-radius: var(--r-lg);
}
.hero__tick {
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  padding: 6px 12px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-sm);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ocean);
}
.hero__coord {
  position: absolute;
  left: var(--s-3);
  bottom: var(--s-3);
  padding: 8px 12px;
  background: rgba(6, 42, 61, 0.86);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ocean-tint);
}
@media (max-width: 880px) {
  .hero__inner {
    grid-template-columns: 1fr;
    gap: var(--s-8);
    padding-block: var(--s-10);
  }
  .hero__content {
    order: 1;
    max-width: none;
  }
  .hero__media {
    order: 2;
  }
  .hero__media img {
    height: 300px;
  }
}

/* -- Interior page header — Cadastral Editorial masthead ------------------
   Shared by Dienstleistungen/Team/Kontakt/legal pages (PageHeader.tsx):
   roofline eyebrow + oversized title (+dek) over the hero's survey grid,
   anchored by a hairline, instead of a bare title floating in whitespace. */
.page-header {
  position: relative;
  overflow: hidden;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.page-header__grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(120% 120% at 85% 0%, #000 22%, transparent 74%);
  mask-image: radial-gradient(120% 120% at 85% 0%, #000 22%, transparent 74%);
}
.page-header__inner {
  position: relative;
  z-index: 1;
  padding-block: var(--s-16) var(--s-10);
}
.page-header__title {
  margin-top: var(--s-3);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.6rem, 4.4vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.012em;
  color: var(--ocean-deep);
}
.page-header__intro {
  margin-top: var(--s-4);
  max-width: 52ch;
  font-size: var(--fs-body-lg);
  color: var(--ink-soft);
}

/* Light-on-dark ghost button — kept for any dark-section CTA (the hero is
   now light; this remains available for `.section--ocean-deep` contexts). */
.btn--ghost-light {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.6);
  color: var(--paper);
}
.btn--ghost-light:hover {
  border-color: var(--paper);
  background: rgba(255, 255, 255, 0.1);
}
.btn--ghost-light:active {
  background: rgba(255, 255, 255, 0.16);
}

@media (max-width: 639px) {
  .hero {
    min-height: 78vh;
  }
  .hero__content {
    padding-block: var(--s-16) var(--s-12);
  }
}

/* -- 2/3. Quick-action bar (fused to the hero — Privera pattern) ------------
   One joined strip on the hero's bottom edge: four hairline-separated cells,
   arrow affordance sliding on hover, "Schaden melden" as the filled primary
   cell. Replaces the earlier four floating tiles. */
.quick-bar {
  background: var(--wash, var(--mist));
  border-bottom: 1px solid var(--line);
}
.quick-bar__inner {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.quick-bar__cell {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-6) var(--s-5);
  border-left: 1px solid var(--line);
  text-decoration: none;
  color: var(--ink);
  transition: background var(--dur) var(--ease);
}
.quick-bar__cell:first-child {
  border-left: none;
}
.quick-bar__cell:hover,
.quick-bar__cell:focus-visible {
  background: var(--paper);
  color: var(--ink);
}
.quick-bar__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 42px;
  height: 42px;
  border: 1px solid var(--line-strong, var(--line));
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--ocean);
}
.quick-bar__icon svg {
  width: 21px;
  height: 21px;
}
.quick-bar__copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.quick-bar__label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.02rem;
  letter-spacing: -0.005em;
}
.quick-bar__desc {
  font-size: var(--fs-sm);
  color: var(--stone);
}
.quick-bar__arrow {
  margin-left: auto;
  font-family: var(--font-mono);
  color: var(--ocean);
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.quick-bar__cell:hover .quick-bar__arrow,
.quick-bar__cell:focus-visible .quick-bar__arrow {
  opacity: 1;
  transform: translateX(0);
}
.quick-bar__cell--primary {
  background: var(--ocean);
  color: var(--paper);
}
.quick-bar__cell--primary .quick-bar__icon {
  background: rgba(255, 255, 255, 0.14);
  border-color: transparent;
  color: var(--paper);
}
.quick-bar__cell--primary .quick-bar__desc {
  color: var(--ocean-tint);
}
.quick-bar__cell--primary .quick-bar__arrow {
  color: var(--paper);
}
.quick-bar__cell--primary:hover,
.quick-bar__cell--primary:focus-visible {
  background: var(--ocean-deep);
  color: var(--paper);
}
@media (max-width: 959px) {
  .quick-bar__inner {
    grid-template-columns: repeat(2, 1fr);
  }
  .quick-bar__cell:nth-child(3) {
    border-left: none;
  }
  .quick-bar__cell:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
}
@media (max-width: 539px) {
  .quick-bar__inner {
    grid-template-columns: 1fr;
  }
  .quick-bar__cell {
    border-left: none;
    border-top: 1px solid var(--line);
  }
  .quick-bar__cell:first-child {
    border-top: none;
  }
}

/* -- 4. Services — image-led cards (Bewy/Wincasa pattern) ------------------- */
.service-card {
  display: block;
  padding: 0;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.service-card:hover,
.service-card:focus-visible {
  color: inherit;
  border-color: var(--ocean);
  transform: translateY(-4px);
  box-shadow: var(--shadow-card);
}
.service-card__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
}
.service-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.45s var(--ease);
}
.service-card:hover .service-card__media img {
  transform: scale(1.05);
}
/* Mono index chip — the cadastral numbering carried onto the card itself. */
.service-card__num {
  position: absolute;
  top: var(--s-3);
  left: var(--s-3);
  padding: 5px 9px;
  background: rgba(6, 42, 61, 0.88);
  color: var(--ocean-tint);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  border-radius: var(--r-sm);
}
.service-card__body {
  padding: var(--s-6);
}
/* Roofline signature atop the card copy (echoes the eyebrow mark). */
.service-card__body::before {
  content: "";
  display: block;
  width: 32px;
  height: 12px;
  margin-bottom: var(--s-4);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 11'%3E%3Cpath d='M1 10 L15 1 L29 10' fill='none' stroke='%230A3B54' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left center;
}
.service-card__body p {
  margin-top: var(--s-2);
}
.service-card__link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--ocean);
  text-decoration: none;
}
.service-card__arrow {
  display: inline-block;
  transition: transform var(--dur) var(--ease);
}
.service-card:hover .service-card__arrow,
.service-card:focus-visible .service-card__arrow {
  transform: translateX(4px);
}

/* -- 5. Featured listings / PropertyCard (reused by Task 10) -------------- */
.property-card {
  position: relative;
  display: block;
  color: inherit;
  text-decoration: none;
}
.property-card:hover,
.property-card:focus-visible {
  color: inherit;
  text-decoration: none;
}
.property-card__badges {
  position: absolute;
  top: var(--s-3);
  left: var(--s-3);
  z-index: 2;
  display: flex;
  gap: var(--s-2);
}
.property-card__title {
  margin-top: var(--s-1);
}
.property-card__price {
  margin-top: var(--s-3);
  /* Money is data: the card price speaks in the same mono voice as the
     detail page's headline price and the spec table, never in the UI sans. */
  font-family: var(--font-mono);
  font-size: var(--fs-body-lg);
  letter-spacing: -0.03em;
  color: var(--ocean-deep);
}
.property-card__price strong {
  font-weight: 400;
}

/* -- 6. Stats band (Storey concrete-promise pattern) ----------------------- */
/* Inverted cadastral grid texture over the deep-ocean band — the signature
   motif, echoing the hero's survey grid. */
.stats-band {
  position: relative;
  overflow: hidden;
}
.stats-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: linear-gradient(rgba(255, 255, 255, 0.11) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.11) 1px, transparent 1px);
  background-size: 64px 64px;
}
.stats-band__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--s-8);
  text-align: center;
}
.stats-band__value {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: clamp(2.1rem, 1.5rem + 2.4vw, 3.2rem);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--paper);
  line-height: 1;
}
.stats-band__label {
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ocean-tint);
}

/* -- 6b. About + stats band (merged intro/stats — design elevation r2) ------ */
.about-band {
  position: relative;
  overflow: hidden;
}
.about-band__grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: linear-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.1) 1px, transparent 1px);
  background-size: 64px 64px;
}
/* The claim leads the band: eyebrow labels the block, the claim states the
   position, a hairline closes it, and the two columns below explain it. The
   lead is a sibling of __inner rather than a row inside it, so it spans the
   full width instead of being trapped in the 1.1fr copy column. */
.about-band__lead {
  position: relative;
  z-index: 1;
  margin-bottom: var(--s-10);
}
.about-band__claim {
  /* The one place on this page where type is allowed to be the loudest thing.
     Everything else here is deliberately even and quiet, and this is the only
     sentence WIKO wrote about themselves — so it is set above the page's own
     section titles rather than level with them. No quotation marks: quoting a
     company's own position turns it into a testimonial. */
  margin: 0.6rem 0 0;
  max-width: 22ch;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.15rem, 1.5rem + 2.5vw, 3.4rem);
  line-height: 1.12;
  letter-spacing: -0.012em;
  color: var(--paper);
}
.about-band__lead::after {
  content: "";
  display: block;
  margin-top: var(--s-8);
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}
.about-band__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--s-16);
  align-items: center;
}
.about-band .eyebrow,
.about-band .eyebrow__idx,
.about-band__copy .eyebrow,
.about-band__copy .eyebrow__idx {
  color: var(--paper);
}
/* The roofline mark follows the eyebrow, which now sits in __lead rather than
   __copy — scoped to the band so it holds in either position. */
.about-band .eyebrow::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 8'%3E%3Cpath d='M1 7 L7 2 L13 7' fill='none' stroke='%23EAF1F5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.about-band__copy .section-title {
  color: var(--paper);
}
.about-band__text {
  max-width: 46ch;
  font-size: var(--fs-body-lg);
  color: var(--ocean-tint);
}
.about-band__stats {
  display: grid;
  gap: var(--s-6);
}
.about-band__stat {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding-left: var(--s-5);
  border-left: 2px solid rgba(255, 255, 255, 0.22);
}
.about-band__stat b {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: clamp(1.95rem, 1.4rem + 1.9vw, 2.9rem);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--paper);
}
.about-band__stat span {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #9fb4c0;
}
@media (max-width: 880px) {
  .about-band__inner {
    grid-template-columns: 1fr;
    gap: var(--s-10);
  }
}

/* -- Scroll-reveal + count-up (src/public-js/main.ts) -----------------------
   Progressive: markup is visible by default; main.ts adds `reveal-init` to
   <html> when JS runs, which arms the hidden state, then the observer adds
   `.is-revealed` per element. No JS -> no class -> nothing ever hidden.
   Reduced motion: main.ts skips arming entirely (plus the global rule). */
.reveal-init [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.reveal-init [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}
/* Staggered children (cards) inside a revealed grid. */
.reveal-init [data-reveal-stagger] > * {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
}
.reveal-init [data-reveal].is-revealed [data-reveal-stagger] > *,
.reveal-init [data-reveal-stagger].is-revealed > * {
  opacity: 1;
  transform: none;
}
.reveal-init [data-reveal-stagger] > *:nth-child(2) {
  transition-delay: 90ms;
}
.reveal-init [data-reveal-stagger] > *:nth-child(3) {
  transition-delay: 180ms;
}
.reveal-init [data-reveal-stagger] > *:nth-child(4) {
  transition-delay: 270ms;
}

/* Sticky header gains a hairline shadow once the page scrolls (main.ts), and
   turns fully opaque at the same moment. At rest the frosted 92% ground sits
   over nothing but the hero, so it costs nothing; the instant content starts
   sliding underneath it becomes a defect — on the listing pages the property
   photos ghost straight through the nav, and a card caught half behind the
   header and half below it reads as though the chrome were slicing it in two
   (reported from a screenshot: "the filter bar cuts across the cards"). A
   blur cannot rescue 8% transparency over a photograph; opacity can. */
.site-header.is-scrolled {
  box-shadow: 0 6px 24px -18px rgba(20, 24, 29, 0.35);
  background: var(--paper);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* -- 7. Team preview --------------------------------------------------------- */
/* Three staff → three columns that fill the container width (aligned with the
   rest of the homepage's grid--3 sections), so the row reads as centred rather
   than left-packed. Straight to one column on phones — no orphaned last card. */
.team-preview__grid {
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 599px) {
  .team-preview__grid {
    grid-template-columns: 1fr;
  }
}

.team-card__media {
  aspect-ratio: 1 / 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--mist);
  /* Photo-less members render an intentional empty frame (client supplies
     real photography later) — hairline border so it reads as a placeholder
     slot, not a broken image. */
  border: 1px solid var(--line);
}
.team-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.45s var(--ease);
}
.team-card:hover .team-card__media img {
  transform: scale(1.05);
}
.team-card__name {
  margin-top: var(--s-3);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.1875rem;
  letter-spacing: -0.005em;
}
.team-card__role {
  margin-top: var(--s-1);
}

/* -- Round-3: recruitment tile (open-role card in the team grid) -------------
   A single ocean-blue card with an animated "shimmer" sweep. Not a jobs
   subsystem (brief §1.4) — one CTA tile linking to /kontakt. Stays inside the
   monochrome palette (ocean/steel + white). */
/* The recruitment tile is the lone 4th item in the team grid, so on the 3-column
   desktop layout it would sit alone in the left column — place it in the centre
   column instead so it reads as centred. (At <=959px the grid is 2 columns and
   it pairs with the third portrait; at <=599px it stacks full-width.) */
@media (min-width: 960px) {
  .team-grid .team-card--recruit {
    grid-column: 2;
  }
}
.team-card--recruit {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 0.4rem;
  padding: var(--s-6);
  border: none;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--ocean-deep) 0%, var(--ocean) 55%, var(--ocean-bright) 100%);
  color: #fff;
  text-decoration: none;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.team-card--recruit:hover,
.team-card--recruit:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md, 0 12px 32px rgba(6, 42, 61, 0.28));
}
/* The sheen: a soft diagonal highlight sweeping across the card, behind the
   text (z-index -1 within the card's own stacking context). Killed by the
   global prefers-reduced-motion rule that zeroes animation durations. */
.team-card--recruit::after {
  content: "";
  position: absolute;
  inset: -2px;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    115deg,
    transparent 32%,
    rgba(255, 255, 255, 0.16) 46%,
    rgba(255, 255, 255, 0.34) 50%,
    rgba(255, 255, 255, 0.16) 54%,
    transparent 68%
  );
  transform: translateX(-120%);
  animation: recruit-shimmer 4.8s var(--ease) infinite;
}
@keyframes recruit-shimmer {
  0% {
    transform: translateX(-120%);
  }
  55%,
  100% {
    transform: translateX(120%);
  }
}
.team-card--recruit .team-card__name {
  margin-top: 0;
  color: #fff;
}
.team-card__recruit-eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
}
.team-card__recruit-role {
  color: rgba(255, 255, 255, 0.86);
  font-size: var(--fs-sm);
}
/* Compact white pill CTA, centred (client choice: Option A, "u centru"). Small
   and dezent — the card stays content-height, not enlarged. */
.team-card__recruit-cta {
  margin-top: var(--s-3);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: #fff;
  color: var(--ocean);
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 0.8rem;
  padding: 0.5rem 1rem;
  border-radius: 999px;
  transition: box-shadow var(--dur) var(--ease);
}
.team-card--recruit:hover .team-card__recruit-cta,
.team-card--recruit:focus-visible .team-card__recruit-cta {
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
}
.team-card__recruit-arrow {
  transition: transform 0.25s var(--ease);
}
.team-card--recruit:hover .team-card__recruit-arrow,
.team-card--recruit:focus-visible .team-card__recruit-arrow {
  transform: translateX(3px);
}

/* -- Round-3: partner network split into two labelled rows ------------------ */
.partner-groups {
  display: grid;
  gap: 2.2rem;
}
.partner-group {
  display: grid;
  gap: 0.85rem;
}
.partner-group__label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ocean);
}

/* -- Round-3: labelled reachability numbers (footer + /kontakt) ------------- */
.site-footer__contact-line,
.kontakt-info__contact-line {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.site-footer__contact-label,
.kontakt-info__contact-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
}

/* -- Round-3: functional white office map (/kontakt) ------------------------
   Leaflet + CARTO Positron light tiles. Container carries an address fallback
   until office-map.js upgrades it; controls/attribution tuned to monochrome. */
.office-map-wrap {
  width: 100%;
}
.office-map {
  position: relative;
  /* Contain Leaflet's internal z-indexes (panes 400, controls 1000) in the
     map's own stacking context so they never paint over the sticky header. */
  isolation: isolate;
  z-index: 0;
  height: 360px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  overflow: hidden;
  background: var(--paper);
}
/* White ground behind the light tiles (Leaflet's default is grey). */
.leaflet-container {
  background: #fff;
  font-family: var(--font-mono);
}
.office-map__fallback {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  text-align: center;
  color: var(--ink-soft);
}
.office-map__fallback address {
  font-style: normal;
  line-height: 1.5;
}
.office-map__pin {
  color: var(--ocean);
  font-size: 1.4rem;
}
.office-map--ready .office-map__fallback {
  display: none;
}
.office-pin {
  background: none;
  border: none;
}
.office-map .leaflet-control-zoom {
  border: none;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.office-map .leaflet-control-zoom a {
  width: 32px;
  height: 32px;
  line-height: 32px;
  color: var(--ocean);
  background: #fff;
  border: none;
  font-weight: 600;
}
.office-map .leaflet-control-zoom a:hover {
  background: var(--ocean-tint);
  color: var(--ocean-deep);
}
.office-map .leaflet-control-attribution {
  background: rgba(255, 255, 255, 0.82);
  color: var(--stone);
  font-size: 0.62rem;
}
.office-map .leaflet-control-attribution a {
  color: var(--ocean);
}
@media (max-width: 599px) {
  .office-map {
    height: 280px;
  }
}

/* -- Round-3 §8: reference / development projects (/referenzen) -------------- */
.project-card {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.project-card__media {
  aspect-ratio: 3 / 2;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--mist);
  overflow: hidden;
}
.project-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.45s var(--ease);
}
.project-card:hover .project-card__media img {
  transform: scale(1.04);
}
/* Placeholder frame for a project whose photo hasn't arrived yet. */
.project-card__pending {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
}
/* "In Entwicklung" badge (client Oct 2026): overlay pill, top-left on the
   photo, for projects still under construction. Ocean on the image with a
   steel status dot. Sits above the img zoom (which only scales the <img>). */
.project-card__badge {
  position: absolute;
  top: 0.65rem;
  left: 0.65rem;
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.42em 0.7em;
  background: var(--ocean);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  border-radius: 2px;
  box-shadow: 0 2px 8px rgba(6, 42, 61, 0.28);
}
.project-card__badge-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--steel);
  box-shadow: 0 0 0 0 rgba(138, 169, 187, 0.55);
  animation: project-badge-pulse 2.4s ease-out infinite;
}
@keyframes project-badge-pulse {
  0% { box-shadow: 0 0 0 0 rgba(138, 169, 187, 0.55); }
  70% { box-shadow: 0 0 0 7px rgba(138, 169, 187, 0); }
  100% { box-shadow: 0 0 0 0 rgba(138, 169, 187, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .project-card__badge-dot { animation: none; }
}
.project-card__body {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: var(--s-5);
}
.project-card__title {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ocean);
}
.project-card__place {
  margin: 0;
}
.project-card__addr {
  margin: 0;
}
.services-index__more {
  margin-top: var(--s-8);
}

/* -- 8. Partner carousel ---------------------------------------------------
   Seamless CSS marquee: `.partner-carousel__track` holds two identical
   `.partner-carousel__group`s, and the keyframe translates by exactly -50%
   (== one group's width). `src/public-js/main.ts`'s `setupPartnerCarousel`
   toggles `.is-paused` (hover/focus) and `.partner-carousel--static`
   (prefers-reduced-motion) — see that file's doc comment. */
.partner-carousel {
  overflow: hidden;
  /* Edge fade so the marquee's cut-off tiles dissolve instead of clipping hard. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.partner-carousel__track {
  display: flex;
  width: max-content;
  animation: partner-scroll 32s linear infinite;
}
.partner-carousel__track.is-paused {
  animation-play-state: paused;
}
.partner-carousel__group {
  display: flex;
  align-items: center;
  gap: var(--s-10);
  flex: none;
  padding-inline-end: var(--s-10);
}

.partner-carousel--static .partner-carousel__track {
  animation: none;
  width: 100%;
}
.partner-carousel--static .partner-carousel__group[aria-hidden] {
  display: none;
}
.partner-carousel--static .partner-carousel__group:not([aria-hidden]) {
  flex-wrap: wrap;
  justify-content: center;
  width: 100%;
  padding-inline-end: 0;
}

@keyframes partner-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* Each logo sits in a white tile with a hairline border so ANY logo —
   pale, coloured, or a placeholder — reads with contrast against the mist
   section and the strip looks structured/premium. The logo fills most of
   the tile (small padding, no grayscale/opacity wash — pale logos must
   stay legible); hover = border + lift. */
.partner-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 190px;
  height: 92px;
  flex: none;
  padding: 10px 14px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.partner-logo:hover,
.partner-logo:focus-visible {
  border-color: var(--ocean);
  transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}
.partner-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.partner-logo__fallback {
  font-size: var(--fs-sm);
  color: var(--stone);
  text-align: center;
}

/* -- 9. Contact band --------------------------------------------------------- */
.contact-band {
  padding-block: var(--s-20, 5rem);
}
.contact-band__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-8);
}
.contact-band__text {
  max-width: 40rem;
}
.contact-band__claim {
  margin-top: var(--s-2);
}
.contact-band__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-top: var(--s-6);
}
.contact-band__meta {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
}

/* =========================================================================
   Static pages, Team, Kontakt/Schadenmeldung shells, 404 — Task 8. Builds
   on Tasks 5-7's tokens/components only (.section/.container/.card/.btn/
   .field/.label/.input/.textarea/.select/.grid/.eyebrow) — no new colors,
   no inline styles. NotfallBanner uses the locked --ocean accent (never an
   off-palette red/orange) for its "attention" treatment, per the brief.
   ========================================================================= */

/* -- generic page header band (Page.tsx / Kontakt.tsx / Schadenmeldung.tsx) -
   A soft --mist band separates the header from the white content below,
   echoing the homepage's alternating section rhythm. `padding-bottom`
   below intentionally overrides `.section`'s own (same specificity — wins
   by cascade order, same technique `.section--mist` etc. already use) so
   the band doesn't carry double whitespace into the section right after it. */
.page-hero {
  background: var(--mist);
  padding-bottom: var(--s-10);
}
.page-hero__inner {
  max-width: 46rem;
}
.page-hero__media {
  margin-top: var(--s-6);
  aspect-ratio: 16 / 9;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--paper);
}
.page-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* -- rich-text body (pages.body_html, rendered raw — already-sanitized CMS
   HTML, see Page.tsx's doc comment) — real typography for headings/lists/
   links/quotes instead of unstyled browser defaults. Constrained to a
   comfortable reading width (68ch); vertical rhythm via `> * + *` at the
   base .stack gap, with headings stepping up. */
.prose {
  max-width: 68ch;
}
.prose > * + * {
  margin-top: var(--s-4);
}
.prose h2 {
  margin-top: var(--s-8);
  font-size: var(--fs-h2);
}
.prose h3,
.prose h4 {
  margin-top: var(--s-6);
}
.prose ul,
.prose ol {
  padding-left: var(--s-6);
  color: var(--ink-soft);
}
.prose li + li {
  margin-top: var(--s-2);
}
.prose blockquote {
  padding-left: var(--s-4);
  border-left: 3px solid var(--ocean);
  color: var(--ink-soft);
  font-style: italic;
}
.prose strong {
  color: var(--ink);
}
.prose img {
  border-radius: var(--r-md);
}
/* CMS document links (TipTap "Dokument verlinken" inserts plain /media/…
   hrefs — the sanitizer allows no class attribute, so the selector targets
   the href; brief §3.1.2 "downloadable documents" on services pages). */
.prose a[href^="/media/"] {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--ocean);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.prose a[href^="/media/"]::before {
  content: "↓";
  color: var(--ocean);
}
.prose a[href^="/media/"]:hover,
.prose a[href^="/media/"]:focus-visible {
  border-color: var(--ocean);
  background: var(--ocean-tint);
}

/* -- Services-page conversion layout (brief §3.1.2 internal links) --------- */
.page-body__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--s-16);
  align-items: start;
}
.page-cta {
  position: sticky;
  top: calc(var(--site-header-h, 0px) + var(--s-6));
}
.page-cta__card {
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--shadow-card);
}
/* Roofline signature atop the card (same device as service cards). */
.page-cta__card::before {
  content: "";
  display: block;
  width: 32px;
  height: 12px;
  margin-bottom: var(--s-4);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 11'%3E%3Cpath d='M1 10 L15 1 L29 10' fill='none' stroke='%230A3B54' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
}
.page-cta__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  color: var(--ocean-deep);
}
.page-cta__text {
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
}
.page-cta__btn {
  width: 100%;
  justify-content: center;
  margin-top: var(--s-4);
}
.page-cta__phone {
  display: block;
  margin-top: var(--s-3);
  text-align: center;
  font-family: var(--font-mono);
  font-weight: 400;
  color: var(--ocean);
  text-decoration: none;
}
.page-cta__phone:hover {
  color: var(--ocean-deep);
  text-decoration: underline;
}
@media (max-width: 880px) {
  .page-body__grid {
    grid-template-columns: 1fr;
    gap: var(--s-8);
  }
  .page-cta {
    position: static;
  }
}

/* -- Team page (full cards — Team.tsx's TeamCard, staff + external
   partners in the same format, brief 3.1.3). `.team-card__media`/
   `__name`/`__role` are already global (Task 7's homepage TeamPreview) —
   only the extra contact/bio rows below are new. */
.team-card--full {
  text-align: left;
}
/* Same auto-fit-to-4 trap the listing grid documents (`.listing-results
   .grid--3`): a fourth team member turns the row into four 250px columns,
   which is too narrow for a bio at 18px or an unbroken e-mail address.
   Cap at 3 and step down on the same breakpoints as the listing. */
.team-grid {
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 959px) {
  .team-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 599px) {
  .team-grid {
    grid-template-columns: 1fr;
  }
}
.team-card__contact {
  margin-top: var(--s-2);
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  font-size: var(--fs-sm);
}
.team-card__bio {
  margin-top: var(--s-3);
}

/* -- Kontakt shell (Kontakt.tsx) --------------------------------------------- */
.kontakt__grid {
  display: grid;
  gap: var(--s-10);
  grid-template-columns: minmax(280px, 380px) 1fr;
  align-items: start;
}
@media (max-width: 879px) {
  .kontakt__grid {
    grid-template-columns: 1fr;
  }
}
.kontakt-info__address {
  color: var(--ink-soft);
  font-style: normal;
}
.kontakt-info__contact {
  margin: 0;
  padding: 0;
  list-style: none;
}
.kontakt-info__hours ul {
  margin-top: var(--s-1);
  padding: 0;
  list-style: none;
}
.kontakt-info__hours li + li {
  margin-top: var(--s-1);
}

/* (Legacy .office-map placeholder styles removed — the /kontakt office map is
   now the functional Leaflet map styled earlier in this file; property detail
   uses .property-map. Those stale rules were overriding the real map's size.) */

/* -- Schadenmeldung shell (Schadenmeldung.tsx) — long multi-section form
   presented as numbered cadastral steps (brief §3.1.7's required groups:
   contact / property / description / uploads), with a "what happens next"
   sidebar. Pure CSS counters — no markup numbering to maintain. */
.schaden__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--s-10);
  align-items: start;
}
@media (max-width: 960px) {
  .schaden__grid {
    grid-template-columns: 1fr;
  }
}
.schaden-form {
  counter-reset: schaden-step;
}
.schaden-form fieldset + fieldset {
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}
.schaden-form legend.fs-h3 {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
}
.schaden-form legend.fs-h3::before {
  counter-increment: schaden-step;
  content: counter(schaden-step, decimal-leading-zero);
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  color: var(--ocean);
}

/* File input styled as a drop-target (CSS only — the native input keeps
   full keyboard/AT behavior). */
.input--file {
  padding: var(--s-5);
  border-style: dashed;
  background: var(--mist);
  cursor: pointer;
}
.input--file::file-selector-button {
  margin-right: var(--s-4);
  padding: 9px 14px;
  border: 1px solid var(--line-strong, var(--line));
  border-radius: var(--r-sm);
  background: var(--paper);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--ocean);
  cursor: pointer;
}
.input--file:hover {
  border-color: var(--ocean);
}

/* Sidebar: next-steps + Notfall cards. */
.schaden-side {
  position: sticky;
  top: calc(var(--site-header-h, 0px) + var(--s-6));
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}
@media (max-width: 960px) {
  .schaden-side {
    position: static;
  }
}
.schaden-side__card {
  padding: var(--s-6);
}
.schaden-side__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
  color: var(--ocean-deep);
  margin-bottom: var(--s-4);
}
.schaden-steps {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: schaden-next;
}
.schaden-steps li {
  position: relative;
  padding-left: var(--s-8);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.schaden-steps li + li {
  margin-top: var(--s-4);
}
.schaden-steps li::before {
  counter-increment: schaden-next;
  content: counter(schaden-next, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 2px;
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--ocean);
}
.schaden-steps b {
  font-weight: 600;
  color: var(--ink);
}
.schaden-steps span {
  font-size: var(--fs-sm);
  color: var(--stone);
}
.schaden-side__card--notfall {
  border-color: var(--ocean);
}
.schaden-side__phone {
  display: block;
  margin-top: var(--s-3);
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 1.1rem;
  color: var(--ocean);
  text-decoration: none;
}
.schaden-side__phone:hover {
  color: var(--ocean-deep);
  text-decoration: underline;
}

/* Submission-confirmation shell (brief §3.1.7) — hidden until the Phase-4
   submit handler unhides it. */
.form-success {
  padding: var(--s-8);
  text-align: center;
}
.form-success__mark {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--ocean);
  color: var(--paper);
  font-size: 1.2rem;
  margin-bottom: var(--s-4);
}
.form-success__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.3rem;
  letter-spacing: -0.02em;
  color: var(--ocean-deep);
}
.form-success__text {
  margin-top: var(--s-2);
  color: var(--ink-soft);
}
.schaden__main .form-success {
  margin-bottom: var(--s-6);
}

/* -- Forms — fieldset/legend reset + checkbox group (both new to Task 8;
   `.field`/`.label`/`.input`/`.textarea`/`.select` are already Task 5's).
   Disabled submit buttons (the Kontakt/Schadenmeldung shells' `data-
   pending-api` treatment): `pointer-events: none` also suppresses `:hover`
   (no separate hover override needed) so a disabled primary button never
   visually reacts to the cursor. */
fieldset {
  margin: 0;
  padding: 0;
  border: none;
}
legend {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h3);
  color: var(--ink);
}
.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-5);
}
.checkbox {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  cursor: pointer;
}
.checkbox input[type="checkbox"] {
  width: 1.15em;
  height: 1.15em;
  accent-color: var(--ocean);
  cursor: pointer;
}

/* Honeypot (Task 23) — off-screen, never `display:none`/`visibility:hidden`
   (some bots skip fields hidden that way but still fill an off-screen one),
   `tabindex="-1"`/`aria-hidden` on the field itself keep it out of the tab
   order and AT tree either way. */
.hp {
  position: absolute;
  left: -9999px;
}

/* Required-field marker (Task 23 — client feedback round 1: phone/e-mail
   mandatory on Schadenmeldung). "Pflichtfeld" as a word, never an asterisk
   — a screen reader reads `*` as "star", which names nothing. Monochrome
   per the brand system: the brand's one accent (--ocean), not a 2nd hue. */
.label__req {
  margin-left: var(--s-2);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ocean);
}

/* Inline form-submission error (Task 23) — role="alert"/aria-live in the
   markup do the announcing; the left border is the only visual cue this
   monochrome system needs beyond the text itself (no 2nd/red hue). */
.form-error {
  margin: 0;
  padding: var(--s-3) var(--s-4);
  border-left: 3px solid var(--ocean);
  background: var(--mist);
  color: var(--ink);
  font-size: var(--fs-sm);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

/* -- NotfallBanner (partials/NotfallBanner.tsx) — a full-bleed --ocean band
   at the very top of Schadenmeldung, deliberately using the locked primary
   accent (not an off-palette warning red/orange) for its urgency. */
.notfall-banner {
  background: var(--ocean);
  color: var(--paper);
}
.notfall-banner__inner {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding-block: var(--s-4);
}
.notfall-banner__icon {
  flex: none;
  width: 28px;
  height: 28px;
  color: var(--ocean-tint);
}
.notfall-banner__text {
  margin: 0;
  color: var(--paper);
}
.notfall-banner__text a {
  color: var(--paper);
  font-weight: 600;
  text-decoration-thickness: 2px;
}
.notfall-banner__text a:hover {
  color: var(--ocean-tint);
}
.notfall-banner__note {
  color: var(--ocean-tint);
}

/* -- Styled 404 (views/NotFound.tsx) ----------------------------------------- */
.not-found__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}

/* =========================================================================
   Property detail — Task 11 (views/PropertyDetail.tsx + partials/*).
   "Cadastral Editorial": mono data, survey-grid map, hairline spec sheet.
   Builds only on the existing tokens/components (.container/.card/.badge/
   .eyebrow/.prose/.property-card) — no new colors.
   ========================================================================= */

/* -- breadcrumb + listing head ------------------------------------------- */
.breadcrumb {
  padding-top: var(--s-6);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.06em;
  color: var(--stone);
}
.breadcrumb a:hover {
  color: var(--ocean);
}
.breadcrumb span {
  color: var(--ocean);
}

.listing-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--s-8);
  flex-wrap: wrap;
  padding: var(--s-4) 0 var(--s-6);
}
.listing-head__badges {
  display: flex;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
  flex-wrap: wrap;
}
.chip {
  display: inline-flex;
  align-items: center;
  padding: 5px 10px;
  border-radius: var(--r-sm);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.chip--kind {
  background: var(--ocean);
  color: var(--paper);
}
.chip--new {
  background: var(--paper);
  border: 1px solid var(--ocean);
  color: var(--ocean);
}
.chip--ref {
  background: var(--mist);
  border: 1px solid var(--line);
  color: var(--stone);
}
.listing-head__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.1rem, 3.8vw, 3.2rem);
  letter-spacing: -0.012em;
  line-height: 1.06;
  color: var(--ocean-deep);
}
.listing-head__addr {
  margin-top: var(--s-2);
  color: var(--ink-soft);
  font-size: var(--fs-body-lg);
}
.listing-head__price {
  text-align: right;
  flex: none;
}
.price__main {
  font-weight: 600;
  font-size: 2rem;
  letter-spacing: -0.01em;
  color: var(--ocean);
}
.price__note {
  margin-top: var(--s-1);
  font-size: var(--fs-sm);
  color: var(--stone);
}

/* -- gallery grid -------------------------------------------------------- */
.gallery {
  margin-bottom: var(--s-10);
}
/* Count-aware frame set (data-gallery-grid = total slide count; the view caps
   visible tiles at 3 = lead + 2 supporting). The 2x2 template holds exactly
   those three — a 4th tile would fall into an implicit auto row and collapse
   the fixed-height grid (the Task 11 launch bug), which the GRID_MAX cap in
   Gallery.tsx now prevents structurally. */
.gallery__grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 10px;
  height: 520px;
  border-radius: var(--r-lg);
  overflow: hidden;
}
.gallery__tile {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--mist);
}
.gallery__tile:first-child {
  grid-row: 1 / 3;
}
/* Exactly two slides: both frames run full height side-by-side. */
.gallery__grid[data-gallery-grid="2"] .gallery__tile:last-child {
  grid-row: 1 / 3;
}
/* A lone image fills the whole frame rather than leaving empty grid cells. */
.gallery__tile:only-child {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}
.gallery__tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur) var(--ease);
}
.gallery__tile:hover img {
  transform: scale(1.04);
}
.gallery__tile:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}
.gallery__more {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  background: rgba(6, 42, 61, 0.55);
  color: var(--paper);
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* -- lightbox (main.ts toggles [hidden]) --------------------------------- */
body.lightbox-open {
  overflow: hidden;
}
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-rows: 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding: clamp(var(--s-4), 4vw, var(--s-10));
  background: rgba(6, 42, 61, 0.92);
}
.lightbox[hidden] {
  display: none;
}
.lightbox__stage {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  min-height: 0;
  min-width: 0;
}
.lightbox__image {
  max-width: 100%;
  max-height: 78vh;
  object-fit: contain;
  border-radius: var(--r-sm);
}
.lightbox__counter {
  color: var(--ocean-tint);
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
}
.lightbox__close,
.lightbox__nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.08);
  color: var(--paper);
  border-radius: 50%;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.lightbox__close:hover,
.lightbox__nav:hover {
  background: rgba(255, 255, 255, 0.18);
  border-color: var(--paper);
}
.lightbox__close {
  position: absolute;
  top: var(--s-4);
  right: var(--s-4);
  width: 40px;
  height: 40px;
  font-size: 1.1rem;
}
.lightbox__nav {
  width: 48px;
  height: 48px;
  font-size: 1.6rem;
  grid-row: 1;
}
.lightbox__nav--prev {
  grid-column: 1;
}
.lightbox__nav--next {
  grid-column: 3;
}
.lightbox__strip {
  grid-column: 1 / 4;
  grid-row: 2;
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  padding-top: var(--s-2);
  justify-content: center;
}
.lightbox__thumb {
  flex: none;
  width: 96px;
  height: 64px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: none;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.lightbox__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.lightbox__thumb.is-active,
.lightbox__thumb:hover,
.lightbox__thumb:focus-visible {
  opacity: 1;
  border-color: var(--steel);
}

/* -- body two-column layout ---------------------------------------------- */
.detail-body {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: var(--s-12);
  align-items: start;
  padding-bottom: var(--section-y);
}
.blk + .blk {
  margin-top: var(--s-10);
}
/* Every block is labelled by a mono roofline eyebrow rendered as its h2
   (.blk__label — Objektdaten style unified across all detail sections). */
.blk__label {
  margin-bottom: var(--s-4);
}
.blk .eyebrow + .specs {
  margin-top: var(--s-4);
}

/* -- spec sheet ---------------------------------------------------------- */
.specs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--line);
  border-left: 1px solid var(--line);
}
.spec {
  padding: var(--s-4) var(--s-5);
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.spec__k {
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stone);
}
.spec__v {
  margin-top: var(--s-2);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--ocean-deep);
}
.spec__v small {
  color: var(--stone);
  font-weight: 400;
  font-size: 0.72rem;
}

/* -- feature tags -------------------------------------------------------- */
.feature-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  list-style: none;
}
.feature-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  color: var(--ink);
}
.feature-tag svg {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--ocean);
}

/* -- documents ----------------------------------------------------------- */
.doc-list {
  list-style: none;
  border-top: 1px solid var(--line);
}
.doc-list__item {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-1);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}
.doc-list__item svg {
  flex: none;
  width: 22px;
  height: 22px;
  color: var(--ocean);
}
.doc-list__title {
  font-weight: 500;
}
.doc-list__meta {
  margin-left: auto;
  font-size: 0.72rem;
  color: var(--stone);
}
.doc-list__dl {
  font-size: 0.72rem;
  color: var(--ocean);
  letter-spacing: 0.06em;
}
.doc-list__item:hover .doc-list__title {
  color: var(--ocean);
}

/* -- location map placeholder (CSP-clean, no external tiles) ------------- */
.property-map {
  position: relative;
  height: 280px;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--line);
  background-color: var(--mist);
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 32px 32px, 32px 32px;
}
.property-map--address-only {
  height: auto;
  padding: var(--s-5);
  background-image: none;
}
.property-map__pin {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -100%);
  color: var(--ocean);
}
.property-map__coord {
  position: absolute;
  left: var(--s-3);
  bottom: var(--s-3);
  background: rgba(6, 42, 61, 0.86);
  color: var(--ocean-tint);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  padding: 7px 11px;
  border-radius: var(--r-sm);
}

/* -- external portal links ----------------------------------------------- */
.ext-links {
  display: flex;
  gap: var(--s-3);
  flex-wrap: wrap;
  list-style: none;
}
.ext-links__item {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 9px var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--ocean);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.ext-links__item:hover {
  border-color: var(--ocean);
  background: var(--ocean-tint);
}

/* -- sidebar ------------------------------------------------------------- */
.detail-side {
  position: sticky;
  top: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}
.detail-side__card {
  padding: var(--s-6);
}

/* -- Besichtigung slot picker (Task 25, public half) — sits above the
   InquiryForm card in the sidebar (Annex A.1); own top-level "card" look
   since its own JSX root isn't wrapped in a `.card` div like InquiryForm's
   is. Same border/radius/padding as `.card` + `.detail-side__card`. */
.slot-picker {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s-6);
}
.slot-picker h2 {
  color: var(--ocean-deep);
}
.slot-picker__slots {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
/* Options stack full-width at every size — the fieldset/legend reset above
   already zeroes fieldset's own border/padding/margin. */
.slot-option {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.slot-option:hover {
  border-color: var(--ocean);
  background: var(--ocean-tint);
}
.slot-option:has(input:checked) {
  border-color: var(--ocean);
  background: var(--ocean-tint);
}
.slot-option input[type="radio"] {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  accent-color: var(--ocean);
  cursor: pointer;
}
.slot-option__when {
  flex: 1;
  font-weight: 500;
  color: var(--ink);
}
.slot-option__left {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--stone);
  white-space: nowrap;
}
/* Optional-field hint (booking's Telefon field: "für die SMS-Bestätigung")
   — subdued, unlike `.label__req`'s uppercase accent badge, since this is a
   courtesy note, not a rule. */
.label__hint {
  margin-left: var(--s-2);
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--stone);
}
.slot-picker--empty p {
  margin-top: var(--s-2);
  color: var(--ink-soft);
}
.slot-picker--empty .btn {
  margin-top: var(--s-4);
}
.inquiry-form__title {
  color: var(--ocean-deep);
}
.keyfacts {
  display: flex;
  flex-direction: column;
}
.keyfact {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-sm);
}
.keyfact:last-child {
  border-bottom: none;
}
.keyfact dt {
  color: var(--stone);
}
.keyfact dd {
  color: var(--ocean-deep);
  font-weight: 500;
}

/* -- similar objects ----------------------------------------------------- */
.similar {
  background: var(--mist);
  border-top: 1px solid var(--line);
}
.similar__title {
  margin-top: var(--s-3);
}
.similar__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-6);
  margin-top: var(--s-6);
}

@media (max-width: 980px) {
  .detail-body {
    grid-template-columns: 1fr;
    gap: var(--s-8);
  }
  .detail-side {
    position: static;
  }
  .gallery__grid {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    height: auto;
  }
  .gallery__tile:first-child,
  .gallery__tile:only-child {
    grid-row: auto;
    grid-column: auto;
  }
  .gallery__tile img {
    height: 240px;
  }
  .specs {
    grid-template-columns: repeat(2, 1fr);
  }
  .similar__grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 560px) {
  .listing-head__price {
    text-align: left;
  }
  .lightbox {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr auto;
  }
  .lightbox__nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
  }
  .lightbox__nav--prev {
    left: var(--s-3);
  }
  .lightbox__nav--next {
    right: var(--s-3);
  }
  .lightbox__stage {
    grid-column: 1;
  }
}

/* -- Listing index (Task 10) ----------------------------------------------
   /mieten + /kaufen (views/ListingIndex.tsx), per the approved mockup
   docs/design/mockups/listing-index-cadastral-editorial.html. APPEND-ONLY
   section: styles only .listing-* classes (plus form controls scoped UNDER
   them) — nothing here modifies rules defined above.

   Sticky note: the bar pins from 880px up only (see the media query right
   below). The header's height is data-dependent (utility row only when
   company contact info is set), so main.ts measures it and exposes
   --site-header-h on <html> (load + resize); with JS off the bar simply
   pins at top:0 beneath the translucent header — clean degradation. */
/* Not pinned at any width (Momčilo, 10 Aug). It sits in the flow directly
   under the header and scrolls away with the results.

   The premium pass had re-pinned it at top:0, which put it *behind* the header
   rather than below it — the header wins on z-index. Corrected, it then parked
   355px of chrome on a 390px phone, with card text ghosting up through the
   translucent surface. The bar is simply static now, which removes both. */
.listing-filters {
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.listing-filters__form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  padding-block: var(--s-4);
}
/* Compact bar-sized controls (the base .select/.input are full-width form
   fields; these rules are new + scoped, they don't touch the base classes). */
.listing-filters .select,
.listing-filters .input {
  width: auto;
  min-width: 150px;
  padding: var(--s-3) var(--s-4);
  font-size: var(--fs-sm);
}
.listing-filters__price {
  max-width: 180px;
}
.listing-filters__submit {
  padding: var(--s-3) var(--s-5);
  font-size: var(--fs-sm);
}
.listing-filters__meta {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-left: auto;
}
.listing-filters__count {
  font-size: var(--fs-sm);
  letter-spacing: 0.04em;
  color: var(--stone);
  white-space: nowrap;
}
.listing-filters__count b {
  color: var(--ocean-deep);
}

/* -- results grid wrapper (tighter than .section — mockup: 34px/72px) ----- */
.listing-results {
  padding-block: var(--s-10) var(--s-20);
}
/* Mockup is a strict 3-column grid; the shared .grid--3 auto-fits to 4
   columns once a page holds 4+ cards, so cap it here (listing only). */
.listing-results .grid--3 {
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 959px) {
  .listing-results .grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 599px) {
  .listing-results .grid--3 {
    grid-template-columns: 1fr;
  }
}

/* -- empty state ----------------------------------------------------------- */
.listing-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-6);
  padding: var(--s-16) var(--s-6);
  text-align: center;
  border: 1px dashed var(--line);
  border-radius: var(--r-md);
}
.listing-empty__title {
  max-width: 36ch;
  color: var(--ocean-deep);
}
.listing-empty__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s-3);
}

/* -- pagination (mono squares, mockup style) ------------------------------- */
.listing-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-12);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
}
.listing-pagination__item {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
a.listing-pagination__item:hover,
a.listing-pagination__item:focus-visible {
  border-color: var(--ocean);
  color: var(--ocean);
}
.listing-pagination__item.is-current {
  background: var(--ocean);
  border-color: var(--ocean);
  color: var(--paper);
}
.listing-pagination__item.is-disabled {
  color: var(--stone);
  opacity: 0.45;
}
.listing-pagination__gap {
  padding-inline: var(--s-1);
  color: var(--stone);
}

@media (max-width: 700px) {
  .listing-filters .select,
  .listing-filters .input {
    flex: 1 1 140px;
    min-width: 0;
    max-width: none;
  }
  .listing-filters__submit {
    flex: 1 1 100%;
  }
  .listing-filters__meta {
    width: 100%;
    margin-left: 0;
    justify-content: space-between;
  }
}

/* =========================================================================
   DESIGN PASS — 10.08.2026
   Ported verbatim from the Claude Design project's premium.css / home.css /
   oglasi.css. Kept as one block at the end of the file rather than merged
   into the rules above so the whole pass stays reviewable and reversible in
   a single diff. Selectors are unprefixed here — being last is enough.

   This supersedes three earlier decisions, deliberately and on the record:
   the three-voice type system, opaque sticky chrome, and the homepage's
   section numbering / utility bar / primary quick tile. See
   docs/superpowers/plans/2026-08-10-wiko-premium-design-pass.md.
   ========================================================================= */

/* --- Typography ---------------------------------------------------------- */
body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1,
h2,
h3,
.section-title,
.listing-head__title {
  text-wrap: balance;
}
p {
  text-wrap: pretty;
}
.mono,
.eyebrow,
.spec__k {
  letter-spacing: 0.12em;
  font-weight: 500;
}
/* Numbers are no longer a separate voice: same face, normal figures. */
.tnum,
.price__main,
.property-card__price {
  font-feature-settings: normal;
  font-variant-numeric: normal;
  letter-spacing: 0;
}
.price__main {
  font-weight: 600;
  font-size: 1.75rem;
  letter-spacing: -0.01em;
}
.price__note {
  letter-spacing: 0.04em;
}
.property-card__price {
  font-size: 1.05rem;
  letter-spacing: 0.01em;
}
.section-title {
  font-size: clamp(1.9rem, 1.4rem + 1.8vw, 2.8rem);
  line-height: 1.08;
  letter-spacing: -0.012em;
}
.eyebrow {
  font-size: 0.72rem;
  letter-spacing: 0.15em;
}
.page-header .eyebrow {
  margin-bottom: var(--s-2);
}
.fs-h3,
.property-card__title,
.team-card__name {
  font-size: 1.3rem;
  line-height: 1.28;
  letter-spacing: -0.005em;
}
.spec__k {
  letter-spacing: 0.1em;
}
.spec__v {
  font-size: 1.02rem;
}

/* --- Header: glass hairline instead of a solid bar ----------------------- */
.site-header__utility {
  display: none;
}
.site-header {
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.site-header.is-scrolled {
  background: rgba(255, 255, 255, 0.92);
  box-shadow: none;
}
/* Logo and bar scaled +35% on 10.08.2026 (46 → 62px, 0.9 → 1.2rem): the whole
   header grows with the mark rather than the logo floating in the old height.
   `--site-header-h` is measured at runtime by main.ts, so every sticky offset
   follows on its own. */
.site-header__logo-img {
  height: 62px;
  transition: height 0.25s var(--ease);
}
.site-header__main-inner {
  padding-block: 1.2rem;
  gap: 2.5rem;
}
/* Child combinators on purpose: these are the TOP-LEVEL nav links only. An
   unscoped `.site-header__nav a` matches the Dienstleistungen panel too, and
   since it sits later in the file it beat `.site-header__sub a` on equal
   specificity — which stripped the panel's horizontal padding and pushed its
   labels against the left edge.

   1.05rem, not the 1.4rem a literal +35% would give: the nav is wayfinding,
   not display type, and at 20px it starts competing with the hero serif. This
   moves it off the --fs-sm step (secondary text) and just under --fs-body, so
   it reads as primary interface against the taller bar. Size, weight and
   colour are fine in the stacked mobile panel too, so they stay unguarded. */
.site-header__nav > ul > li > a {
  font-size: 1.05rem;
  font-weight: 500;
  color: var(--ink-soft);
}

/* Everything that describes the horizontal BAR — the row gap, the centring,
   the tight vertical padding on a link that sits in a row, and the underline
   geometry — is desktop-only. Below 880px the nav is a stacked panel with its
   own rules near line 1103, and these were quietly beating them: the 2.2rem
   row gap became 35px of dead air between every item, and `padding: .35rem 0`
   stripped the gutter so every label sat flush against the screen edge. */
@media (min-width: 880px) {
  .site-header__nav > ul {
    gap: 2.2rem;
    justify-content: center;
  }
  .site-header__nav > ul > li > a {
    padding: 0.35rem 0;
  }
  .site-header__nav > ul > li > a::after {
    height: 1px;
    bottom: 0;
  }
}

/* The sub-disclosure button exists only where hover does not. Guarded rather
   than left bare: an unguarded `display: none` here sits after the mobile
   block and would beat its `display: flex` on source order — the same trap
   that has bitten the row gap, the link padding and the pill. */
@media (min-width: 880px) {
  .site-header__sub-toggle {
    display: none;
  }
}

/* --- Dienstleistungen panel ---------------------------------------------- */
/* Desktop only. Below 880px the panel is not a floating card at all — it is
   stacked inline under Dienstleistungen (see the max-width:879px block near
   line 1017). Without this guard these rules would out-order that block on
   equal specificity and drag a 248px min-width and a card shadow into the
   mobile menu. */
@media (min-width: 880px) {
  /* Same frame language as the cards: 12px, two-layer depth, hairline. The rows
     are inset from the panel edge so the hover band reads as a row rather than a
     full-bleed stripe. */
  .site-header__nav ul.site-header__sub {
    min-width: 248px;
    padding: 6px;
    border-radius: 12px;
    box-shadow:
      0 1px 2px rgba(15, 35, 52, 0.05),
      0 14px 34px rgba(15, 35, 52, 0.1);
  }
  .site-header__sub a {
    padding: 9px 14px;
    border-radius: 8px;
    font-size: var(--fs-sm);
    /* The body line-height (1.65) is for prose; a menu row wants to sit closer
       to its own label. */
    line-height: 1.35;
    font-weight: 400;
    color: var(--ink-soft);
    transition:
      background 0.16s var(--ease),
      color 0.16s var(--ease);
  }
  .site-header__sub li.site-header__sub-all {
    margin-top: 6px;
    padding-top: 6px;
  }
  /* The one echo of the hero's ghost link — the arrow steps forward on hover. */
  .site-header__sub-all a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    /* Sits apart from the three service rows by colour and weight, not by size —
       the old rule shrank it to 0.72rem, which read as a footnote. */
    font-size: var(--fs-sm);
    letter-spacing: 0;
    font-weight: 500;
    color: var(--ocean);
  }
  /* `.site-header__nav a::after` (line ~914) draws the nav underline: absolute,
     2px tall, scaleX(0) until hover. Reusing that pseudo-element for the arrow
     means undoing every one of those properties, or the glyph renders as an
     invisible 2px absolutely-positioned sliver. */
  .site-header__sub-all a::after {
    content: "\2192";
    position: static;
    height: auto;
    background: none;
    transform: none;
    transition: transform 0.2s var(--ease);
  }
  .site-header__sub-all a:hover::after,
  .site-header__sub-all a:focus-visible::after {
    transform: translateX(3px);
  }
}

/* These two belong outside the desktop guard: the divider is undone below
   880px by its own rule, and the pill must keep its shape on mobile — an
   earlier edit had swallowed both into the min-width block, which also left a
   max-width rule nested inside a min-width one, where it could never match. */
.site-header__actions {
  padding-left: 2.2rem;
  border-left: 1px solid var(--line);
}
/* The pill shape holds at every width; its generous padding does not. On the
   desktop bar it grows with the nav so the primary action is not the smallest
   thing there. On a 390px bar that same padding made it 181px wide — nearly
   half the row — and it was silently overriding the small-phone trim that
   already exists at max-width 479px. */
.site-header__damage-btn {
  border-radius: 999px;
}
@media (min-width: 880px) {
  .site-header__damage-btn {
    padding: 0.72rem 1.7rem;
    font-size: 0.95rem;
  }
}
@media (max-width: 879px) {
  .site-header__actions {
    padding-left: 0;
    border-left: none;
  }
}

/* Between the breakpoint and ~1080px the six items, the divider and the pill
   no longer clear the container at the wide spacing — the row overflowed by
   23px at 900px. Tighten the gaps rather than shrink the type back down. */
@media (min-width: 880px) and (max-width: 1080px) {
  .site-header__nav > ul {
    gap: 1.4rem;
  }
  .site-header__actions {
    padding-left: 1.4rem;
  }
  .site-header__damage-btn {
    padding: 0.72rem 1.25rem;
  }
}

/* --- Cards: quieter surfaces, graded depth ------------------------------- */
.card,
.service-card,
.team-card--full {
  border-radius: 12px;
}
.card {
  box-shadow:
    0 1px 2px rgba(15, 35, 52, 0.05),
    0 10px 30px rgba(15, 35, 52, 0.06);
}
.card:hover {
  box-shadow:
    0 2px 6px rgba(15, 35, 52, 0.07),
    0 20px 48px rgba(15, 35, 52, 0.11);
}
.card__media,
.service-card__media,
.team-card__media {
  border-radius: 0;
  overflow: hidden;
}
.card__media img {
  transition: transform 0.5s var(--ease);
}
.property-card {
  border: 1px solid rgba(15, 35, 52, 0.07);
  box-shadow: none;
  transition:
    transform 0.3s var(--ease),
    box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease);
}
.property-card:hover {
  transform: translateY(-4px);
  border-color: rgba(15, 35, 52, 0.14);
  box-shadow:
    0 2px 6px rgba(15, 35, 52, 0.05),
    0 22px 48px rgba(15, 35, 52, 0.1);
}
.property-card:hover .card__media img {
  transform: scale(1.045);
}
.property-card__title {
  transition: color 0.25s var(--ease);
}
.property-card:hover .property-card__title {
  color: var(--ocean);
}
.badge {
  letter-spacing: 0.08em;
  font-weight: 600;
}

/* --- Buttons ------------------------------------------------------------- */
.btn {
  letter-spacing: 0.015em;
}
.btn--primary {
  box-shadow: 0 8px 22px rgba(15, 35, 52, 0.16);
}
.btn--primary:hover {
  box-shadow: 0 10px 28px rgba(15, 35, 52, 0.22);
}
.btn--ghost-light {
  border: 1px solid rgba(255, 255, 255, 0.45);
}

/* --- Partners: a drifting hairline band ---------------------------------- */
/* The 2026-08-10 design pass froze this band into a static wrapped grid
   (`animation: none`, duplicate group hidden, edge mask removed). Momčilo
   asked for the drift back on 20 Aug — the client's own feedback was that a
   "durchlaufender Partnerfirmen-Bereich" was missing, and it was: the markup
   and the JS were always here, the CSS had switched them off.
   The band keeps the hairline frame the design pass introduced; what moves is
   the content inside it. Slow on purpose — a logo strip that races reads as an
   ad rotator, and this one belongs to a Swiss property manager. */
.partner-carousel {
  overflow: hidden;
  /* Wider fade than the original 6%: once marks are moving, the eye goes to
     the rim, and a hard clip there is the first thing you notice. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.partner-carousel__track {
  width: max-content;
  /* Duration = marks-per-group x seconds-per-mark, per breakpoint: the loop
     travels exactly one group's width, so both the group width (per-mark,
     via --carousel-count set inline by PartnerCarousel) and the viewport
     (per-breakpoint seconds) have to feed it. ~5s per ~110px mark on a
     phone and ~7.5s per ~160px mark on a desktop both hold the drift near
     21 px/s — calm enough to read as a standing band, not a rotator. */
  animation: partner-scroll calc(var(--carousel-count, 6) * 5s) linear infinite;
}
.partner-carousel__group {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  column-gap: 2.2rem;
  width: auto;
  padding: 1.6rem 0;
  padding-inline-end: 2.2rem;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
/* Reduced motion falls back to the wrapped grid defined earlier in this file.
   Those rules are `.partner-carousel--static …` (two classes), so they already
   outrank everything above on specificity — but the mask and the band's own
   inline-end padding are set on single-class selectors here, so they need an
   explicit release or a motionless grid gets faded at both edges. */
.partner-carousel--static {
  -webkit-mask-image: none;
  mask-image: none;
}
.partner-carousel--static .partner-carousel__group {
  column-gap: 3.2rem;
  row-gap: 1.4rem;
  padding-inline-end: 0;
}
.partner-logo {
  display: inline-flex;
  align-items: center;
  width: auto;
  height: auto;
  flex: none;
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  margin: 0;
  text-decoration: none;
}
/* Cap the artwork, not the box: partner logos arrive from the client at
   whatever size their agency exported, and the band has to absorb that
   without any of them dictating the rhythm. Height is the constraint because
   optical weight in a horizontal strip reads off cap height, not area. */
.partner-logo img {
  width: auto;
  height: 48px;
  max-width: 180px;
  object-fit: contain;
  /* Mono+hover (round-3 client decision): the band reads as a disciplined
     monochrome strip and reveals each partner's real brand colour on hover.
     The colour reveal is also mirrored on keyboard focus (below) and dropped
     under prefers-reduced-motion. */
  filter: grayscale(1);
  opacity: 0.72;
  transition: filter 0.3s var(--ease), opacity 0.3s var(--ease);
}
.partner-logo:focus-visible img {
  filter: none;
  opacity: 1;
}
/* A near-square lockup (icon stacked over wordmark) reads as a stamp under
   the shared cap — a taller cap restores its optical mass next to the wide
   marks. The class comes from the server, keyed off the asset's real
   width/height ratio. */
.partner-logo--tall img {
  height: 58px;
}
/* The static (reduced-motion) grid hides the in-group repeats the marquee
   needs to fill its band — a wrapped grid needs each partner once. */
.partner-carousel--static .partner-logo[aria-hidden] {
  display: none;
}
.partner-logo:hover {
  background: transparent;
  transform: none;
  box-shadow: none;
  border: none;
}
/* The text fallback for a partner with no logo file. It has to sit at the
   same optical weight as the 30/40px artwork beside it, so it is sized to
   match cap height rather than to look good on its own. */
.partner-logo__fallback {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 400;
  letter-spacing: 0.005em;
  text-transform: none;
  white-space: nowrap;
  color: var(--ink-soft);
  transition: color 0.25s var(--ease);
}
.partner-logo:hover .partner-logo__fallback {
  color: var(--ocean);
}
.partner-logo:hover img {
  filter: none;
  opacity: 1;
}
/* Desktop-only, and guarded — the band is one strip at every width, but on a
   phone a 40px mark with 4.5rem of air either side puts barely two in view and
   the loop stops reading as continuous. (Every rule that describes the wide
   layout lives inside this query on purpose: an unguarded one beats the
   narrow rules on source order, which is how five separate mobile
   regressions got in.) */
@media (min-width: 880px) {
  .partner-carousel__track {
    animation-duration: calc(var(--carousel-count, 6) * 7.5s);
  }
  .partner-carousel__group {
    column-gap: 3.5rem;
    padding: 2rem 0;
    padding-inline-end: 3.5rem;
  }
  /* 84px base: a stacked wide mark like Seco Immobilien — skyline over
     wordmark — leaves its wordmark small, and its e/o/b counters only read
     as open once the whole mark is ~84px. Verified on the real render at 1x
     DPI (not just retina), where 68px still filled them. Near-square lockups
     (DAWO) get the taller --tall cap so they keep their presence. */
  .partner-logo img {
    height: 68px;
    max-width: 220px;
  }
  .partner-logo--tall img {
    height: 84px;
  }
  .partner-logo__fallback {
    font-size: clamp(1.35rem, 1.1rem + 0.9vw, 1.8rem);
  }
}

/* --- Feature tags: pills ------------------------------------------------- */
.feature-tag {
  border-radius: 999px;
  padding: 0.5rem 0.95rem;
  background: var(--paper);
  border: 1px solid rgba(15, 35, 52, 0.12);
  box-shadow: 0 1px 3px rgba(15, 35, 52, 0.05);
  gap: 0.5rem;
  transition:
    transform 0.25s var(--ease),
    box-shadow 0.25s var(--ease),
    border-color 0.25s var(--ease);
}
.feature-tag svg {
  width: 18px;
  height: 18px;
  color: var(--ocean);
}
.feature-tag:hover {
  transform: translateY(-2px);
  border-color: rgba(28, 74, 99, 0.3);
  box-shadow: 0 6px 16px rgba(15, 35, 52, 0.08);
}

/* --- Forms --------------------------------------------------------------- */
.input,
.select,
.textarea {
  border-radius: 8px;
}
.input:focus,
.select:focus,
.textarea:focus {
  box-shadow: 0 0 0 3px rgba(28, 74, 99, 0.14);
}

/* --- Listing: frosted sticky filter bar ---------------------------------- */
/* Not sticky. The design pass pinned it, which buried it under the header
   (both were sticky at top: 0 and the header wins on z-index) and, once that
   was corrected, left 355px of a 390px-wide phone screen permanently occupied
   by chrome — with card text ghosting through both translucent surfaces.
   Momčilo's call, 10 Aug: the bar sits in the flow under the navbar and
   scrolls away with the results. */
.listing-filters {
  /* Solid, not frosted. Nothing passes underneath a static bar, so the blur
     was a compositing cost with no effect and the translucency only muddied
     the band. Same warm tint the design chose, at full opacity. */
  background: #faf9f6;
  border-bottom: 1px solid rgba(15, 35, 52, 0.08);
}
.listing-filters .select,
.listing-filters .input {
  border-radius: 999px;
  border-color: rgba(15, 35, 52, 0.14);
  background: var(--paper);
  transition:
    border-color 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}
.listing-filters .select:hover,
.listing-filters .input:hover {
  border-color: rgba(15, 35, 52, 0.3);
}
.listing-filters__submit {
  border-radius: 999px;
}
.listing-pagination__item {
  border-radius: 8px;
  transition:
    background 0.2s var(--ease),
    border-color 0.2s var(--ease),
    color 0.2s var(--ease);
}
.listing-pagination__item:hover {
  background: rgba(28, 74, 99, 0.06);
}

/* --- Detail page --------------------------------------------------------- */
.gallery__tile,
.hero__media,
.page-hero__media {
  border-radius: 12px;
  overflow: hidden;
}
.gallery__tile {
  position: relative;
}
.gallery__tile::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  background: linear-gradient(180deg, transparent 65%, rgba(15, 35, 52, 0.18));
}
.gallery__tile:hover::after {
  opacity: 1;
}
.gallery__tile img {
  transition: transform 0.5s var(--ease);
}
.lightbox__image {
  transition: opacity 0.18s var(--ease);
}
.lightbox__thumb {
  border: 2px solid transparent;
  border-radius: 6px;
  transition:
    opacity 0.2s var(--ease),
    border-color 0.2s var(--ease);
}
.spec {
  transition: background 0.2s var(--ease);
  border-radius: 6px;
}
.spec:hover {
  background: rgba(28, 74, 99, 0.04);
}
.detail-side {
  position: sticky;
  top: calc(var(--site-header-h, 88px) + 24px);
  align-self: start;
}
.similar {
  border-top: 1px solid rgba(15, 35, 52, 0.07);
}
.doc-list__item {
  transition:
    background 0.2s var(--ease),
    transform 0.2s var(--ease);
}
.doc-list__item:hover {
  background: rgba(28, 74, 99, 0.04);
  transform: translateX(3px);
}

/* --- Footer -------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.site-footer__grid {
  gap: var(--s-12);
  padding-block: clamp(3.5rem, 6vw, 5.5rem);
}
.site-footer__logo-img {
  height: 64px;
  margin-bottom: 1.2rem;
}
.site-footer a {
  transition:
    color 0.2s var(--ease),
    opacity 0.2s var(--ease);
}
.site-footer a:hover {
  color: var(--paper);
}
.site-footer h3 {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.55);
}
.site-footer__address {
  color: rgba(255, 255, 255, 0.72);
}
.site-footer__hours {
  padding-top: 1.1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.site-footer__hours li {
  color: rgba(255, 255, 255, 0.6);
}
.site-footer__social {
  padding: 6px 16px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 999px;
  font-size: 0.82rem;
  transition:
    border-color 0.2s var(--ease),
    background 0.2s var(--ease);
}
.site-footer__social:hover {
  border-color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.06);
}
.site-footer__bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.site-footer__bottom-inner {
  padding-block: 1.1rem;
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.45);
}

/* --- Team: photo placeholder until client photography lands -------------- */
.team-card__media {
  position: relative;
  min-height: 220px;
  background: repeating-linear-gradient(
    45deg,
    rgba(15, 35, 52, 0.045) 0 10px,
    rgba(15, 35, 52, 0.015) 10px 20px
  );
}
.team-card__media:empty::after {
  content: "Foto folgt";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(15, 35, 52, 0.4);
}

/* External-partner tiles hold a company logo, not a portrait: contain the
   artwork on paper instead of cover-cropping it in the 1:1 frame, and let
   the placeholder caption say what is actually pending. */
.team-card--partner .team-card__media:empty::after {
  content: "Logo folgt";
}
.team-card--partner .team-card__media:has(img) {
  background: var(--paper);
}
.team-card--partner .team-card__media img {
  object-fit: contain;
  padding: 14%;
}
/* The photo-zoom hover reads as a lens on a portrait but as a glitch on a
   contained logo. */
.team-card--partner:hover .team-card__media img {
  transform: none;
}

/* The staff grid's pending state — the window between the demo people going
   dark and the client's portraits arriving. A framed placeholder slot in the
   same visual language as the photo-less media frame, not a bare sentence. */
.team-pending {
  max-width: 560px;
  margin-inline: auto;
  padding: 3rem 2rem;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: repeating-linear-gradient(
    45deg,
    rgba(15, 35, 52, 0.03) 0 10px,
    rgba(15, 35, 52, 0.012) 10px 20px
  );
}
.team-pending__label {
  display: block;
  margin-bottom: 0.9rem;
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--stone);
}
.team-pending__text {
  margin: 0;
  color: var(--ink-soft);
}

/* --- Homepage ------------------------------------------------------------ */
.hero__content {
  max-width: 34rem;
}
.hero__subtitle {
  font-size: 1.08rem;
  line-height: 1.65;
  color: var(--stone);
}
/* The About band tells the same figures better — the hero repeat confused. */
.hero__trust {
  display: none;
}
/* Section numbering off: quieter eyebrows. */
.eyebrow__idx {
  display: none;
}
.hero__actions {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.4rem;
}
.hero__actions .btn {
  width: auto;
  flex: 0 0 auto;
}
.hero__actions .btn--primary {
  padding: 0.95rem 2.4rem;
  border-radius: 999px;
}
.hero__actions .btn--ghost {
  border: none;
  background: transparent;
  padding: 0.4rem 0;
  box-shadow: none;
  color: var(--ocean);
  font-weight: 600;
}
.hero__actions .btn--ghost::after {
  content: "\2192";
  margin-left: 0.5rem;
  display: inline-block;
  transition: transform 0.25s var(--ease);
}
.hero__actions .btn--ghost:hover {
  background: transparent;
  text-decoration: underline;
  text-underline-offset: 5px;
}
.hero__actions .btn--ghost:hover::after {
  transform: translateX(4px);
}

/* Below 880px the desktop pair stops working: at 390px the pill and the link
   cannot share a row, so they stack — and once stacked their labels do not
   line up, because the pill indents its own by 38px of padding while the bare
   link starts at the container edge. A lone text link under a big pill also
   reads as unfinished rather than quiet.

   So on small screens the second action becomes a real button again: same
   width, same radius, hairline instead of fill. The pair now shares both
   edges, the hierarchy still reads (filled vs outline), and the arrow stays.
   Placed here, after the desktop rules it overrides, rather than up in the
   880px block where it would lose on source order. */
@media (max-width: 879px) {
  .hero__actions {
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-3);
  }
  .hero__actions .btn {
    width: 100%;
  }
  .hero__actions .btn--primary {
    padding: 0.95rem 1.5rem;
  }
  .hero__actions .btn--ghost {
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 0.95rem 1.5rem;
    justify-content: center;
  }
}
/* All four quick-bar cells rank equally — the dark one broke the grid. */
.quick-bar__cell {
  transition: background 0.2s var(--ease);
}
.quick-bar__cell--primary {
  background: transparent;
  color: inherit;
}
.quick-bar__cell--primary .quick-bar__icon {
  background: rgba(28, 74, 99, 0.08);
  border-color: transparent;
  color: var(--ocean);
}
.quick-bar__cell--primary .quick-bar__desc {
  color: var(--stone);
}
.quick-bar__cell--primary .quick-bar__arrow {
  color: var(--ocean);
}
.quick-bar__cell--primary:hover,
.quick-bar__cell--primary:focus-visible {
  background: rgba(28, 74, 99, 0.05);
  color: inherit;
}
.featured {
  padding-top: clamp(4rem, 7vw, 7rem);
}

/* =========================================================================
   Ratgeber / Knowledge Center — Task 27/28. Reuses `.card`, `.eyebrow`,
   `.section-title`, `.grid--3`, `.prose`, `.page-hero-media`/`.page-hero__media`,
   and the `.listing-filters`/`.listing-empty`/`.listing-pagination` idioms
   verbatim (RatgeberListe.tsx) — only genuinely new widgets get new,
   namespaced rules below: the category tiles and the article card's own
   meta spacing.
   ========================================================================= */
/* ── Featured lead — the landing's one bold element ───────────────────────
   A newest-article hero: large serif headline + excerpt left, cover (or a
   monogram plate when coverless) right. The whole block is one link. */
.ratgeber-lead__grid {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: stretch;
  text-decoration: none;
  color: inherit;
}
.ratgeber-lead__grid:hover,
.ratgeber-lead__grid:focus-visible {
  color: inherit;
  text-decoration: none;
}
.ratgeber-lead__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.ratgeber-lead__meta {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin: 0 0 var(--s-4);
  font-size: var(--fs-sm);
  color: var(--stone);
}
.ratgeber-lead__cat {
  color: var(--ocean);
  font-weight: 600;
}
.ratgeber-lead__dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--steel);
}
.ratgeber-lead__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 1.3rem + 2.6vw, 3.25rem);
  line-height: 1.02;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 var(--s-4);
}
.ratgeber-lead__excerpt {
  color: var(--ink-soft);
  font-size: var(--fs-body-lg);
  line-height: 1.55;
  max-width: 42ch;
  margin: 0 0 var(--s-6);
}
.ratgeber-lead__link {
  align-self: flex-start;
  font-weight: 600;
  color: var(--ocean);
  border-bottom: 2px solid var(--ocean);
  padding-bottom: 2px;
}
.ratgeber-lead__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-sm);
  min-height: 340px;
  background: linear-gradient(135deg, var(--ocean-deep), var(--ocean));
}
.ratgeber-lead__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}
.ratgeber-lead__grid:hover .ratgeber-lead__media img {
  transform: scale(1.03);
}
.ratgeber-lead__media--mono {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ocean-deep);
}
.ratgeber-lead__monogram {
  font-family: var(--font-display);
  font-size: clamp(4rem, 8vw, 7rem);
  color: rgba(255, 255, 255, 0.16);
}

/* ── Topic index — a land-register ledger, not arrow tiles ───────────────── */
.ratgeber-ledger {
  border-top: 1px solid var(--line);
}
.ratgeber-ledger__row {
  display: grid;
  grid-template-columns: minmax(9rem, 15rem) 1fr auto;
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: center;
  padding: var(--s-5) 0;
  border-bottom: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
  transition: background var(--dur) var(--ease), padding-inline-start var(--dur) var(--ease);
}
.ratgeber-ledger__row:hover,
.ratgeber-ledger__row:focus-visible {
  color: inherit;
  text-decoration: none;
  background: var(--ocean-tint);
  padding-inline-start: var(--s-3);
}
.ratgeber-ledger__name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h3);
  color: var(--ocean-deep);
}
.ratgeber-ledger__desc {
  color: var(--stone);
  font-size: var(--fs-body);
}
.ratgeber-ledger__count {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  white-space: nowrap;
  font-size: var(--fs-sm);
  color: var(--ink);
}
.ratgeber-ledger__count b {
  font-size: 1.15rem;
  font-weight: 600;
}
.ratgeber-ledger__chev {
  color: var(--ocean);
  transition: transform var(--dur) var(--ease);
}
.ratgeber-ledger__row:hover .ratgeber-ledger__chev,
.ratgeber-ledger__row:focus-visible .ratgeber-ledger__chev {
  transform: translateX(4px);
}

.ratgeber-latest__all {
  display: inline-block;
  margin-top: var(--s-8);
  font-weight: 600;
  color: var(--ocean);
  text-decoration: none;
  border-bottom: 2px solid var(--ocean);
  padding-bottom: 2px;
}

/* -- listing-mode results wrapper (same padding rhythm as .listing-results) */
.ratgeber-results {
  padding-block: var(--s-10) var(--s-20);
}
.ratgeber-article__body {
  max-width: 44rem;
}

/* ── Editorial entry — the shared card (landing rail, listing, related) ─────
   Hairline top rule, no drop shadow; cover image OR a monogram plate when the
   article has no cover. Replaces the old rounded `.article-card`/`.card`. */
.ratgeber-entries {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.25rem, 3vw, 2.5rem);
}
.ratgeber-entry {
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
  border-top: 2px solid var(--ink);
  padding-top: var(--s-4);
  transition: border-color var(--dur) var(--ease);
}
.ratgeber-entry:hover,
.ratgeber-entry:focus-visible {
  color: inherit;
  text-decoration: none;
  border-color: var(--ocean);
}
.ratgeber-entry__plate {
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: var(--r-sm);
  margin-bottom: var(--s-4);
  background: var(--ocean-tint);
}
.ratgeber-entry__plate img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.45s var(--ease);
}
.ratgeber-entry:hover .ratgeber-entry__plate img {
  transform: scale(1.04);
}
.ratgeber-entry__plate--mono {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--mist);
  border: 1px solid var(--line);
}
.ratgeber-entry__monogram {
  font-family: var(--font-display);
  font-size: 2.6rem;
  color: var(--steel);
}
.ratgeber-entry__cat {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ocean);
  margin-bottom: var(--s-1);
}
.ratgeber-entry__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h3);
  line-height: 1.1;
  color: var(--ink);
  margin: 0 0 var(--s-2);
}
.ratgeber-entry__excerpt {
  color: var(--stone);
  font-size: var(--fs-sm);
  line-height: 1.5;
  margin: 0 0 var(--s-3);
}
.ratgeber-entry__date {
  margin: auto 0 0;
  color: var(--stone);
  font-size: var(--fs-sm);
}

/* Three across on desktop; single column below 880px. */
@media (min-width: 880px) {
  .ratgeber-entries {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (max-width: 880px) {
  .ratgeber-lead__grid {
    grid-template-columns: 1fr;
  }
  .ratgeber-lead__media {
    order: -1;
    min-height: 220px;
  }
  .ratgeber-ledger__row {
    grid-template-columns: 1fr auto;
  }
  .ratgeber-ledger__desc {
    display: none;
  }
}

/* --- Motion -------------------------------------------------------------- */
.reveal-init [data-reveal] {
  transform: translateY(18px);
}
.reveal-init [data-reveal-stagger] > * {
  transition-duration: 0.55s;
}

/* Must stay last: the reduced-motion guard wins over everything above. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* -- §8 reference project detail (/referenzen/<slug>) — Dossier layout (V2) -- */
.project-card--link{cursor:pointer;text-decoration:none;color:inherit;transition:box-shadow var(--dur) var(--ease),transform var(--dur) var(--ease)}
.project-card--link:hover{box-shadow:0 12px 32px rgba(6,42,61,.12);transform:translateY(-2px)}
.refdetail__back{display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;font-weight:600;color:var(--ocean);text-decoration:none;margin-bottom:1.4rem}
.refdetail__back:hover{color:var(--ocean-deep)}
.refdetail__grid{display:grid;grid-template-columns:minmax(280px,34%) 1fr;gap:2.4rem;align-items:start}
.refdetail__rail{position:sticky;top:calc(var(--site-header-h,101px) + 1rem);display:flex;flex-direction:column;gap:1rem}
.refdetail__place{font-family:var(--font-display);font-weight:400;font-size:clamp(2.2rem,1.7rem+2.2vw,3.2rem);line-height:1;margin:.5rem 0 0}
.refdetail__addr{color:var(--ink-soft);line-height:1.5}
.refdetail__dl{border-top:1px solid var(--line);margin:.4rem 0 0}
.refdetail__row{display:flex;justify-content:space-between;gap:1rem;padding:.7rem 0;border-bottom:1px solid var(--line)}
.refdetail__row dt{font-size:.7rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--stone)}
.refdetail__row dd{margin:0;font-size:.95rem;color:var(--ink);text-align:right;font-variant-numeric:tabular-nums}
.refdetail__intro{color:var(--ink-soft);line-height:1.6;font-size:.98rem;max-width:60ch}
.refdetail__cta{align-self:flex-start;margin-top:.3rem}
.refdetail__media{display:flex;flex-direction:column;gap:16px}
.refdetail__media img{width:100%;border-radius:var(--r-md);object-fit:cover}
.refdetail__media img:first-child{aspect-ratio:16/10}
.refdetail__pending{aspect-ratio:16/10;display:flex;align-items:center;justify-content:center;background:var(--mist);border:1px solid var(--line);border-radius:var(--r-md);color:var(--steel);letter-spacing:.14em;text-transform:uppercase;font-size:.8rem}
@media (max-width:820px){
  .refdetail__grid{grid-template-columns:1fr}
  .refdetail__rail{position:static}
}

/* ===========================================================================
   Ask WIKO — assistant widget (separate module).
   Floating launcher + chat panel, rendered site-wide via Layout
   (AssistantWidget.tsx); behaviour in public-js/main.ts. Monochrome +
   --ocean, in-family with the rest of the site. Adds no new design tokens.
   =========================================================================== */
.wiko-assistant { position: fixed; right: 20px; bottom: 20px; z-index: 60; font-family: var(--font-body); }
.wiko-assistant__sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.wiko-assistant__launcher { display: inline-flex; align-items: center; gap: .5rem; background: var(--ocean); color: #fff; border: none; border-radius: 999px; padding: .7rem 1.1rem; font: inherit; font-weight: 600; font-size: .95rem; cursor: pointer; box-shadow: 0 10px 24px -8px rgba(6, 42, 61, .4); transition: background .15s, transform .08s; }
.wiko-assistant__launcher:hover { background: var(--ocean-deep); }
.wiko-assistant__launcher:active { transform: scale(.96); }
.wiko-assistant__launcher-icon { width: 20px; height: 20px; flex: none; }
.wiko-assistant.is-open .wiko-assistant__launcher { display: none; }

.wiko-assistant__panel { display: flex; flex-direction: column; width: min(380px, calc(100vw - 40px)); height: min(560px, calc(100vh - 40px)); background: var(--paper); border: 1px solid var(--line); border-radius: 18px; box-shadow: 0 2px 6px rgba(6, 42, 61, .08), 0 30px 60px -24px rgba(6, 42, 61, .4); overflow: hidden; }
.wiko-assistant__panel[hidden] { display: none; }

.wiko-assistant__head { display: flex; align-items: center; gap: .65rem; padding: .85rem 1rem; border-bottom: 1px solid var(--line); }
.wiko-assistant__mark { width: 32px; height: 32px; border-radius: 8px; background: var(--ocean); color: #fff; display: flex; align-items: center; justify-content: center; flex: none; font-family: var(--font-display); font-size: 1.1rem; }
.wiko-assistant__titles { display: flex; flex-direction: column; line-height: 1.15; }
.wiko-assistant__title { font-weight: 600; font-size: .95rem; }
.wiko-assistant__status { display: inline-flex; align-items: center; gap: .35rem; font-size: .72rem; color: var(--stone); }
.wiko-assistant__dot { width: 7px; height: 7px; border-radius: 50%; background: #4bbf7b; }
.wiko-assistant__close { margin-left: auto; width: 32px; height: 32px; border: none; background: none; color: var(--stone); cursor: pointer; border-radius: 8px; display: flex; align-items: center; justify-content: center; }
.wiko-assistant__close:hover { background: var(--mist); color: var(--ink); }
.wiko-assistant__close svg { width: 18px; height: 18px; }

.wiko-assistant__thread { flex: 1; overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: .6rem; }
.wiko-assistant__msg { max-width: 85%; font-size: .9rem; line-height: 1.5; padding: .6rem .8rem; border-radius: 14px; }
.wiko-assistant__msg--bot { align-self: flex-start; background: var(--mist); color: var(--ink); border-bottom-left-radius: 5px; }
.wiko-assistant__msg--user { align-self: flex-end; background: var(--ocean); color: #fff; border-bottom-right-radius: 5px; }
.wiko-assistant__msg a { color: var(--ocean); font-weight: 600; }
.wiko-assistant__msg--user a { color: #fff; }
.wiko-assistant__typing { align-self: flex-start; color: var(--stone); font-size: .85rem; padding: .3rem .2rem; }

.wiko-assistant__cards { align-self: flex-start; width: 85%; display: flex; flex-direction: column; gap: .5rem; }
.wiko-assistant__card { display: flex; gap: .6rem; text-decoration: none; color: inherit; border: 1px solid var(--line); border-radius: 12px; padding: .5rem; transition: box-shadow .15s, transform .15s; }
.wiko-assistant__card:hover { box-shadow: var(--shadow-card); transform: translateY(-1px); }
.wiko-assistant__card-img { width: 66px; height: 52px; flex: none; border-radius: 8px; object-fit: cover; background: var(--mist); }
.wiko-assistant__card-b { display: flex; flex-direction: column; min-width: 0; }
.wiko-assistant__card-t { font-weight: 600; font-size: .82rem; line-height: 1.2; }
.wiko-assistant__card-m { font-size: .72rem; color: var(--stone); }
.wiko-assistant__card-p { font-size: .8rem; color: var(--ocean); font-weight: 600; margin-top: 1px; }
.wiko-assistant__sources { align-self: flex-start; width: 85%; display: flex; flex-direction: column; gap: .25rem; font-size: .82rem; }
.wiko-assistant__sources a { color: var(--ocean); text-decoration: none; }
.wiko-assistant__sources a:hover { text-decoration: underline; }

.wiko-assistant__chips { display: flex; flex-wrap: nowrap; gap: .4rem; padding: .5rem 1rem 0; overflow-x: auto; scrollbar-width: none; }
.wiko-assistant__chips::-webkit-scrollbar { display: none; }
.wiko-assistant__chip { flex: none; white-space: nowrap; font: inherit; font-size: .78rem; font-weight: 600; color: var(--ocean); background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: .4rem .75rem; cursor: pointer; transition: background .15s, border-color .15s; }
.wiko-assistant__chip:hover { background: var(--ocean-tint); border-color: var(--steel); }

.wiko-assistant__composer { display: flex; align-items: center; gap: .5rem; padding: .7rem 1rem 1rem; }
.wiko-assistant__input { flex: 1; font: inherit; font-size: .9rem; padding: .6rem .8rem; border: 1px solid var(--line); border-radius: 999px; background: var(--mist); color: var(--ink); }
.wiko-assistant__send { width: 40px; height: 40px; flex: none; border: none; border-radius: 50%; background: var(--ocean); color: #fff; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background .15s, transform .08s; }
.wiko-assistant__send:hover { background: var(--ocean-deep); }
.wiko-assistant__send:active { transform: scale(.96); }
.wiko-assistant__send svg { width: 18px; height: 18px; position: relative; left: -1px; }

@media (max-width: 520px) {
  .wiko-assistant { right: 12px; bottom: 12px; }
  .wiko-assistant__panel { width: calc(100vw - 24px); height: min(72vh, 540px); }
}

/* Ask WIKO — Phase 2 confirmation cards (in-chat booking/inquiry/damage) */
.wiko-assistant__chip--action { border-color: var(--steel); background: var(--ocean-tint); }
.wiko-assistant__form-card { align-self: flex-start; width: 92%; display: flex; flex-direction: column; gap: .5rem; background: var(--paper); border: 1px solid var(--line); border-radius: 12px; padding: .8rem; }
.wiko-assistant__field { display: flex; flex-direction: column; gap: .2rem; font-size: .78rem; color: var(--stone); }
.wiko-assistant__cinput { font: inherit; font-size: .88rem; color: var(--ink); padding: .5rem .6rem; border: 1px solid var(--line); border-radius: 8px; background: var(--mist); }
.wiko-assistant__cinput:focus-visible { outline: 2px solid var(--ocean); outline-offset: 1px; }
.wiko-assistant__cerror { font-size: .8rem; color: #b3261e; }
.wiko-assistant__csubmit { font: inherit; font-weight: 600; font-size: .85rem; color: #fff; background: var(--ocean); border: none; border-radius: 999px; padding: .55rem .9rem; cursor: pointer; align-self: flex-start; transition: background .15s, transform .08s; }
.wiko-assistant__csubmit:hover { background: var(--ocean-deep); }
.wiko-assistant__csubmit:active { transform: scale(.97); }
.wiko-assistant__csubmit:disabled { opacity: .6; cursor: default; }
