/* ========================================
   re|spic|ere — Fine-line bookshelf
   ======================================== */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

/* Visually hidden, available to assistive technology. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* Honeypot field — same visually-hidden trick, but bot-fillable */
.cf-honeypot {
  position: absolute;
  left: -9999px; top: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* Skip link — visually hidden until keyboard-focused */
.skip-link {
  position: absolute;
  left: 8px;
  top: -100px;
  z-index: 200;
  padding: 8px 16px;
  background: var(--ink);
  color: var(--bg);
  font-size: 0.85rem;
  text-decoration: none;
  transition: top 0.2s ease;
}
.skip-link:focus {
  top: 8px;
}

@font-face {
  font-family: 'Whitney Book';
  src: url('../fonts/Whitney-Book-Bas.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Whitney Book';
  src: url('../fonts/Whitney-BookItal-Bas.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Whitney Book';
  src: url('../fonts/Whitney-Light-Bas.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Whitney Book';
  src: url('../fonts/Whitney-Medium-Bas.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Whitney Book';
  src: url('../fonts/Whitney-Semibold-Bas.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* --- Cormorant Garamond (self-hosted; previously loaded from Google Fonts).
   Self-hosting removes the third-party DNS lookup, eliminates a privacy
   leak to Google, and lets the browser prioritize these requests as
   same-origin. We provide only the latin + latin-ext subsets — the rest
   (cyrillic, vietnamese, etc.) aren't needed for German content.
   font-display: swap keeps the page interactive while the font loads;
   the fallback (Georgia, serif) is metrically similar enough to avoid
   major reflow. --- */
@font-face {
  font-family: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-300.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-300-ext.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-300i.woff2') format('woff2');
  font-weight: 300;
  font-style: italic;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-300i-ext.woff2') format('woff2');
  font-weight: 300;
  font-style: italic;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-400-ext.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-400i.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-400i-ext.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
  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;
}
/* SemiBold (600) — the heading weight. Real cuts (downloaded from the
   Google Fonts OFL release), not browser-synthesized faux bold. */
@font-face {
  font-family: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-600-ext.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-600i.woff2') format('woff2');
  font-weight: 600;
  font-style: italic;
  font-display: swap;
  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: 'Cormorant Garamond';
  src: url('../fonts/cormorant-garamond-600i-ext.woff2') format('woff2');
  font-weight: 600;
  font-style: italic;
  font-display: swap;
  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;
}

:root {
  /* Paper tone sampled from the design-reference photograph (Michael
     Kenna, Hokkaido — bare trees in snow): a slightly deeper, creamier
     warm white. Also mirrored in the theme-color meta (index.html) and
     favicon.svg. (A darker Canela-specimen greige #e6e2de was tried and
     reverted 2026-06-12.) */
  --bg: #edeae5;
  --bg-alt: #e6e2dc;  /* one step deeper than --bg (currently unused) */
  --ink: #1a1918;
  --ink-light: #3d3c3a;
  --body: #4d4b49;
  /* --mid darkened to match --body (was #5c5a58): all running text now
     reads in the same inkier gray — closer to the Kenna-print contrast
     of charcoal on paper white. */
  --mid: #4d4b49;
  --muted: #807e7b;
  --faint: #a8a6a3;
  --bg-dark: #c9c4bb;
  --line: #d5d3d0;
  --line-light: #e6e5e2;
  --serif: 'Cormorant Garamond', Georgia, serif;
  --sans: 'Whitney Book', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --divider-w: 36px;
  /* Baseline rhythm grid.
     All text line-heights and vertical margins are multiples of --rhythm so
     that horizontal text lines align across all columns in the bookshelf
     layout, regardless of which heading/body element starts each column.
     1.6rem = 27.2px at the 17px root, matching the body line-height. */
  --rhythm: 1.6rem;
  /* --- Motion scale ---
     Single source of truth for the navigation choreography durations.
     The JS state machine is tuned to these: TRANSITION_TIME in main.js
     (800 ms) covers --t-panel + --t-reveal with headroom, and the 400 ms
     measure point in openSectionDirect assumes --t-panel = 0.6s. If you
     change these, change main.js to match. Secondary fades (opacity on
     dividers/hero-inner) keep literal durations slightly shorter than
     their primary motion — that offset is intentional. */
  --t-hero: 1.2s;        /* hero grow + hero-inner slide (idle pace) */
  --t-hero-exit: 1s;     /* hero collapse/slide-out when a section opens */
  --t-nav: 0.8s;         /* divider + logo-mark strip reveal */
  --t-nav-retract: 0.5s; /* divider strip retract (reverse stagger) */
  --t-panel: 0.6s;       /* section open flex-grow */
  --t-reveal: 0.4s;      /* panel content fade-in + cover fade-out */
}

/* Palette read in the Display-P3 colour space (chosen 2026-11-09 from a
   side-by-side swatch test in Safari). The same channel values as the hex
   palette above, but interpreted in P3: on wide-gamut screens (all recent
   Macs/iPhones) this renders the slightly warmer, richer paper tone the
   palette was tuned by eye in a non-colour-managed preview. The hex values
   remain the fallback for browsers without color() support. Keep both
   lists in sync when changing a colour. */
@supports (color: color(display-p3 0 0 0)) {
  :root {
    --bg: color(display-p3 0.9294 0.9176 0.8980);
    --bg-alt: color(display-p3 0.9020 0.8863 0.8627);
    --ink: color(display-p3 0.1020 0.0980 0.0941);
    --ink-light: color(display-p3 0.2392 0.2353 0.2275);
    --body: color(display-p3 0.3020 0.2941 0.2863);
    --mid: color(display-p3 0.3020 0.2941 0.2863);
    --muted: color(display-p3 0.5020 0.4941 0.4824);
    --faint: color(display-p3 0.6588 0.6510 0.6392);
    --bg-dark: color(display-p3 0.7882 0.7686 0.7333);
    --line: color(display-p3 0.8353 0.8275 0.8157);
    --line-light: color(display-p3 0.9020 0.8980 0.8863);
  }
}

html { font-size: 17px; -webkit-font-smoothing: antialiased; scroll-behavior: smooth; }
body {
  font-family: var(--sans);
  color: var(--mid);
  background: var(--bg);
  line-height: 1.6;
  font-weight: 400;
  overflow: hidden;
  height: 100vh;
  /* orphans/widows=1: allow mid-paragraph column breaks at any line.
     This is the only way to reliably fill columns to the bottom in a
     horizontal-scrolling multi-column layout. Subtitle/heading orphan
     protection is enforced separately via break-after: avoid on the
     specific blocks where it matters (section-break, panel-title, etc). */
  orphans: 1;
  widows: 1;
  /* text-wrap: pretty re-balances the last lines of every paragraph for
     aesthetics, which can shorten paragraphs and create column tail gaps.
     Use the default (auto) so paragraphs fill columns to their natural edge. */
  hyphens: auto;
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 10 5 4;
  -webkit-hyphenate-limit-chars: 10 5 4;
  hyphenate-limit-lines: 2;
  -webkit-hyphenate-limit-lines: 2;
  hyphenate-limit-zone: 12%;
}

#lines-canvas {
  position: fixed; inset: 0;
  pointer-events: none; z-index: 0;
  /* Subtlety lives in the per-line stroke alpha (3–7%, main.js) —
     a canvas-level opacity on top of that made the lines invisible. */
  opacity: 1;
}

/* =========================================================
   BOOKSHELF
   ========================================================= */
.bookshelf {
  position: relative;
  z-index: 1;
  display: flex;
  height: 100vh;
  overflow: hidden;
}

/* =========================================================
   HERO PANEL — shows logo initially, definition after scroll
   ========================================================= */
.hero-panel {
  flex: 1 1 0%;
  min-width: 0;
  overflow: visible;
  display: grid;
  place-items: center;
  grid-template-rows: 15% 1fr 15%;
  text-align: center;
  padding: 0 40px;
  position: relative;
  transition: flex-grow var(--t-hero) cubic-bezier(0.25, 0.1, 0.25, 1),
              padding var(--t-hero) cubic-bezier(0.25, 0.1, 0.25, 1);
}
/* Hero stays visible when spines show (displays definition) */
/* Hero collapses only when a section is active */
.bookshelf.has-active .hero-panel {
  flex-grow: 0;
  padding: 0;
  grid-template-rows: 0 1fr 0;
  transition: flex-grow var(--t-hero-exit) cubic-bezier(0.25, 0.1, 0.25, 1),
              padding var(--t-hero-exit) cubic-bezier(0.25, 0.1, 0.25, 1);
}

/* Hero inner — logo + tagline */
.hero-inner {
  min-width: 400px;
  z-index: 1;
  position: relative;
  grid-row: 2;
  transition: transform var(--t-hero) cubic-bezier(0.25, 0.1, 0.25, 1),
              opacity 0.8s ease;
}
/* Hero slides off smoothly when a section opens */
.bookshelf.has-active .hero-inner {
  transform: translateX(-100vw);
  opacity: 0;
  pointer-events: none;
  transition: transform var(--t-hero-exit) cubic-bezier(0.25, 0.1, 0.25, 1),
              opacity 0.7s ease;
}

.hero-wordmark {
  font-family: var(--serif);
  font-size: clamp(4.5rem, 10vw, 8.5rem);
  font-weight: 300;
  letter-spacing: -0.045em;
  color: var(--ink);
  line-height: 0.9;
  margin-bottom: 0;
  transition: opacity 0.6s ease;
}
/* Logo stays on definition page — hero-inner handles the slide-out */

.pipe {
  color: var(--ink);
  display: inline-block;
  font-weight: 200;
  transform: scaleX(0.5);
  animation: pulse 3s ease-in-out infinite;
}
.pipe:nth-of-type(2) { animation-delay: 1.5s; }
@keyframes pulse {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 0.8; }
}

.hero-tagline {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: calc(100% + 24px);
  width: 100%;
  font-family: var(--serif);
  font-size: clamp(1rem, 1.8vw, 1.4rem);
  font-weight: 300;
  font-style: italic;
  color: var(--muted);
  letter-spacing: 0.04em;
  transition: transform 0.8s cubic-bezier(0.25, 0.1, 0.25, 1),
              opacity 0.6s ease;
}
/* Tagline slides out to the left when definition shows */
.bookshelf.spines-visible .hero-tagline {
  transform: translateX(-150%);
  opacity: 0;
}

/* =========================================================
   HERO DEFINITION — fades in below logo, replacing tagline
   ========================================================= */
.hero-def {
  position: absolute;
  left: 50%;
  transform: translateX(100%);
  top: calc(100% + 24px);
  width: 100%;
  opacity: 0;
  transition: transform 0.8s cubic-bezier(0.25, 0.1, 0.25, 1) 0.2s,
              opacity 0.6s ease 0.2s;
  pointer-events: none;
}
.bookshelf.spines-visible .hero-def {
  transform: translateX(-50%);
  opacity: 1;
  pointer-events: auto;
}
.bookshelf.def-exiting .hero-def {
  transform: translateX(-150%);
  opacity: 0;
  transition: transform 0.6s cubic-bezier(0.25, 0.1, 0.25, 1),
              opacity 0.4s ease;
}
.bookshelf.has-active .hero-def {
  transform: translateX(-150%);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.8s cubic-bezier(0.25, 0.1, 0.25, 1),
              opacity 0.5s ease;
}

/* =========================================================
   SECTION SUBTITLE — typographic byline
   ========================================================= */
.section-subtitle {
  font-family: var(--serif);
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  font-weight: 400;
  font-style: italic;
  color: var(--ink);
  /* Absolute line-height (multiple of --rhythm) keeps subtitle on the same
     baseline grid as the body text, so columns starting with a subtitle and
     columns starting with body text stay aligned. */
  line-height: var(--rhythm);
  letter-spacing: -0.015em;
  /* One rhythm step above the subtitle = one blank line of breathing room.
     For subtitles inside .section-break (which has margin-top: 2*rhythm),
     this collapses into the larger parent margin and is effectively ignored.
     For STANDALONE subtitles (e.g. client-list categories), this is the
     entire vertical separation from the preceding content. */
  margin-top: var(--rhythm);
  margin-bottom: var(--rhythm);
  max-width: 50ch;
  break-inside: avoid;
  break-after: avoid;
  text-wrap: balance;
  hyphens: none;
  /* Vertical rule sits at left:0 (the column's left edge, same x as paragraph
     text). padding-left shifts the SUBTITLE TEXT to the right of the line. */
  position: relative;
  padding-left: 18px;
}
.section-subtitle::before {
  content: '';
  position: absolute;
  left: 0;
  /* Calibrated by direct getClientRects measurement: the box-bottom sits
     ≈3.7 px below the visible text bottom (line-height phantom space), so
     a NEGATIVE CSS bottom would push the rule well past the descenders.
     A small NEGATIVE bottom of -1 keeps the rule ≈5 px past the
     descenders. top: -10 lands ≈5 px above the topmost rendered glyph,
     matching the bottom overshoot. */
  top: -10px;
  bottom: -1px;
  width: 1px;
  background: var(--ink-light);
}

.def-text {
  font-family: var(--serif);
  font-size: clamp(0.88rem, 1.2vw, 1.05rem);
  font-weight: 300;
  color: var(--ink-light);
  line-height: 1.6;
  max-width: 560px;
  margin: 0 auto;
  text-align: left;
}
.def-text .def-hw {
  font-size: 1.6em;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.03em;
  display: block;
  margin-bottom: 10px;
}
.def-text .def-grammar {
  font-style: italic;
  color: var(--mid);
  font-size: 0.85em;
  display: block;
  margin-bottom: 4px;
}
.def-text strong {
  font-weight: 500;
  color: var(--ink);
}
.def-text em {
  font-style: italic;
  color: var(--muted);
}
.def-list {
  list-style: none;
  padding: 0;
  margin: 4px 0 0;
}
.def-list li {
  padding-left: 1.2em;
  text-indent: -1.2em;
  margin-bottom: 0;
  line-height: 1.55;
}

/* Scroll cue */
.scroll-cue {
  position: absolute;
  bottom: calc(15% + 12px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  opacity: 0.4;
  transition: opacity 0.4s ease;
  z-index: 2;
}
.bookshelf.spines-visible .scroll-cue {
  opacity: 0;
  pointer-events: none;
}
.scroll-cue-line {
  width: 1px;
  height: 36px;
  background: var(--line);
  position: relative;
  overflow: hidden;
}
.scroll-cue-line::after {
  content: '';
  position: absolute;
  top: -100%; left: 0;
  width: 100%; height: 100%;
  background: var(--ink);
  animation: scrollPulse 2s ease-in-out infinite;
}
@keyframes scrollPulse {
  0% { top: -100%; }
  50% { top: 0; }
  100% { top: 100%; }
}

/* =========================================================
   LOGO MARK — rotated mini logo, first element
   ========================================================= */
.logo-mark {
  flex: 0 0 0px;
  min-width: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  background: var(--bg);
  border: none;
  border-right: none;
  opacity: 0;
  transition: flex-basis var(--t-nav) cubic-bezier(0.25, 0.1, 0.25, 1) 0.2s,
              min-width var(--t-nav) cubic-bezier(0.25, 0.1, 0.25, 1) 0.2s,
              opacity 0.6s ease 0.3s;
}
.bookshelf.has-active .logo-mark {
  flex-basis: var(--divider-w);
  min-width: var(--divider-w);
  opacity: 1;
  padding: 15vh 0;
}

.logo-mark-text {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 400;
  color: var(--ink);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  letter-spacing: -0.03em;
  transition: color 0.3s ease;
}
.logo-mark:hover {
  background: linear-gradient(to bottom, var(--bg) 15%, var(--bg-dark) 15%, var(--bg-dark) 85%, var(--bg) 85%);
}
.logo-mark:hover .logo-mark-text { color: var(--ink); }

/* =========================================================
   DIVIDERS — thin vertical black lines with labels
   ========================================================= */
.divider {
  flex: 0 0 0px;
  min-width: 0;
  opacity: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  border: none;
  border-left: none;
  background: var(--bg);
  border-image: linear-gradient(to bottom, transparent 15%, var(--ink) 15%, var(--ink) 85%, transparent 85%) 1;
  border-left-width: 1px;
  border-left-style: solid;
  position: relative;
  overflow: hidden;
  z-index: 2;
  transition: flex-basis var(--t-nav) cubic-bezier(0.25, 0.1, 0.25, 1) calc((4 - var(--i, 0)) * 0.05s + 0.3s),
              min-width var(--t-nav) cubic-bezier(0.25, 0.1, 0.25, 1) calc((4 - var(--i, 0)) * 0.05s + 0.3s),
              opacity 0.6s ease calc((4 - var(--i, 0)) * 0.05s + 0.3s),
              padding var(--t-nav) ease calc((4 - var(--i, 0)) * 0.05s + 0.3s),
              background 0.15s ease 0s;
}
.bookshelf.has-active .divider,
.bookshelf.nav-revealed .divider {
  flex-basis: var(--divider-w);
  min-width: var(--divider-w);
  opacity: 1;
  padding: 15vh 0;
}
/* Reverse stagger on retract — last divider disappears first */
.bookshelf.nav-retracting .divider {
  transition: flex-basis var(--t-nav-retract) cubic-bezier(0.25, 0.1, 0.25, 1) calc(var(--i, 0) * 0.05s),
              min-width var(--t-nav-retract) cubic-bezier(0.25, 0.1, 0.25, 1) calc(var(--i, 0) * 0.05s),
              opacity var(--t-reveal) ease calc(var(--i, 0) * 0.05s),
              padding var(--t-nav-retract) ease calc(var(--i, 0) * 0.05s),
              background 0.15s ease 0s;
}

.divider:hover {
  background: linear-gradient(to bottom, var(--bg) 15%, var(--bg-dark) 15%, var(--bg-dark) 85%, var(--bg) 85%);
}
.divider:hover .divider-label { color: var(--ink); }
.divider.active {
  background: linear-gradient(to bottom, var(--bg) 15%, var(--bg-dark) 15%, var(--bg-dark) 85%, var(--bg) 85%);
}
/* Push remaining dividers to the right edge so they don't shift when a section opens */
.panel.active + .divider {
  margin-left: auto;
}
.divider.passed { opacity: 0.55; }
.divider.passed:hover { opacity: 1; }

.divider-label {
  font-family: var(--serif);
  font-size: 1rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--ink);
  writing-mode: vertical-rl;
  text-orientation: mixed;
  transform: rotate(180deg);
  white-space: nowrap;
  transition: color 0.25s ease;
}
.divider:hover .divider-label { color: var(--ink); }
.divider.active .divider-label { color: var(--ink); font-weight: 400; }
/* Sequential intro highlight when nav first appears */
.divider.intro-highlight {
  background: linear-gradient(to bottom, var(--bg) 15%, var(--bg-dark) 15%, var(--bg-dark) 85%, var(--bg) 85%);
}
.divider.intro-highlight .divider-label { color: var(--ink); }

/* =========================================================
   PANELS
   ========================================================= */
.panel {
  flex: 0 0 0%;
  min-width: 0;
  overflow: hidden;
  /* Transparent so the parallax line canvas (z-index 0) shows through
     behind open sections. The ::after cover still paints solid --bg
     during the open choreography, and the page background provides the
     paper tone. */
  background: transparent;
  position: relative;
  /* A CLOSING panel must animate too — otherwise it snaps to 0 and every
     divider to its right teleports ~1200 px in one frame, then slides
     back. Its timing must MATCH whatever grows at the same moment, so the
     summed flex-grow stays 1 every frame and the dividers glide
     monotonically:
       • closing back to hero/nav (has-active removed): the hero regrows
         with --t-hero → the panel shrinks with --t-hero (this rule);
       • section → section (has-active kept): old and new panel both use
         --t-panel (rule below). */
  transition: flex-grow var(--t-hero) cubic-bezier(0.25, 0.1, 0.25, 1);
}
.bookshelf.has-active .panel {
  /* --t-panel is load-bearing: main.js measures column geometry 400 ms
     into the opening transition and re-measures after it settles. */
  transition: flex-grow var(--t-panel) cubic-bezier(0.25, 0.1, 0.25, 1);
}
.panel.active {
  flex-grow: 1;
}

/* Faint section image — scrolls WITH the content and ends exactly at
   the right edge of the section's last column (placePanelBg in main.js
   computes `left` = content end − image width). Since the image is
   ~2.3 columns wide and fades out to its left, it becomes gradually
   visible behind the final columns as the reader approaches the end.
   z-index −1 keeps it BEHIND the column text inside the .panel-scroll
   stacking context. On mobile the @media block overrides this back to
   an absolute full-bleed overlay. */
.panel-bg {
  position: absolute;
  top: 15vh;
  height: calc(100% - 30vh);   /* span the column area between paddings */
  left: 0;                     /* overridden per layout by main.js */
  width: 55vw;
  z-index: -1;
  background-size: cover;
  background-position: center;
  opacity: 0;
  pointer-events: none;
  filter: grayscale(100%);
  mask-image: linear-gradient(to left, rgba(0,0,0,1) 30%, transparent 100%);
  -webkit-mask-image: linear-gradient(to left, rgba(0,0,0,1) 30%, transparent 100%);
  transition: opacity var(--t-reveal) cubic-bezier(0.25, 0.1, 0.25, 1);
}
.panel.active.revealed .panel-bg {
  opacity: 0.12;
}

/* Fixed section heading — stays in top-left while content scrolls */
.panel-title {
  font-family: var(--serif);
  font-size: clamp(1.4rem, 2.2vw, 1.85rem);
  font-weight: 400;
  font-style: italic;
  /* Deep charcoal — headings carry the strongest ink in the palette. */
  color: var(--ink);
  letter-spacing: -0.02em;
  /* 2 rhythm steps gives a generous 54.4px line-height for a ~31px max font,
     while keeping every panel-title line on the baseline grid. */
  line-height: calc(var(--rhythm) * 2);
  max-width: 50ch;
  /* margin-top: 12 keeps the title's vertical-line top INSIDE the panel
     content area (line extends 10 px above title.box.top). */
  margin-top: 12px;
  margin-bottom: var(--rhythm);
  break-after: avoid;
  text-wrap: balance;
  hyphens: none;
  /* Vertical rule sits at left:0 (column-left-edge, aligned with paragraph
     text). padding-left shifts the TITLE TEXT right of the rule. */
  position: relative;
  padding-left: 20px;
}
.panel-title::before {
  content: '';
  position: absolute;
  left: 0;
  /* The line's top is calibrated so it is FLUSH with the top of the
     navigation-divider vertical lines.
       • Navigation divider line top = 15 % of bookshelf height = 15 vh
         (= 135 px at 900 px viewport height).
       • Panel-title top = panel-content padding-top (15 vh) + title
         margin-top (12 px) = 15 vh + 12 px.
       • To align the line top with 15 vh exactly, the ::before's `top`
         must equal -12 px (it sits 12 px above the title box top, which
         lands the line top at exactly the panel-content padding edge,
         which is exactly 15 vh = the nav divider line top). */
  top: -12px;
  bottom: 5px;
  width: 1px;
  background: var(--ink-light);
}

/* --- Panel cover: solid background that hides all layout computation.
   Fades away only after .revealed is added, guaranteeing fully-painted content. --- */
.panel::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--bg);
  z-index: 10;
  pointer-events: none;
  opacity: 1;
  transition: opacity var(--t-reveal) cubic-bezier(0.25, 0.1, 0.25, 1);
}
.panel.active.revealed::after {
  opacity: 0;
}

.panel-scroll {
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
  position: relative;
  z-index: 1;
  opacity: 0;
  transform: translateX(16px);
  transition: opacity var(--t-reveal) cubic-bezier(0.25, 0.1, 0.25, 1),
              transform var(--t-reveal) cubic-bezier(0.25, 0.1, 0.25, 1);
  /* Soft edge fades. Always on (not only while .revealed): the mask has no
     layout effect, and toggling it with .revealed made the edges snap hard
     in the first frame of every close. Mobile overrides it to none. */
  mask-image: linear-gradient(to right, transparent, black 48px, black calc(100% - 48px), transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, black 48px, black calc(100% - 48px), transparent);
}
.panel.active.revealed .panel-scroll {
  opacity: 1;
  transform: translateX(0);
}
.panel-scroll::-webkit-scrollbar { height: 4px; }
.panel-scroll::-webkit-scrollbar-track { background: transparent; }
.panel-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }

/* =========================================================
   ÜBER UNS WRAPPERS — the section's content sits in two semantic
   wrappers (intro narratives / main content). They are transparent to
   the multi-column layout, so the section flows exactly like every
   other panel: heading at the top of col 1, body filling cols 1 → 2 →
   3 → … across the bookshelf. */
@media (min-width: 769px) {
  #ueber-uns .panel-content-side,
  #ueber-uns .panel-content-main {
    display: contents;
  }
}

.panel-content {
  height: 100%;
  /* positioning context for the absolutely placed .panel-bg, so the
     image scrolls with the columns */
  position: relative;
  padding: 15vh 48px 15vh 72px;
  column-width: 320px;
  column-gap: 48px;
  column-rule: none;
  column-fill: auto;
}
/* Trailing spacer — empty columns at the end of each section */
.panel-spacer {
  break-before: column;
  height: 1px;
}

/* =========================================================
   TYPOGRAPHY
   ========================================================= */
/* Cap-height alignment for column-starting elements.
   In CSS column layout, every column starts at the same y-coordinate, but
   the FIRST LINE of text inside an element sits below the box top by the
   font's half-leading — which differs per font-size. With text-box-trim
   the leading above the first line is removed, putting each element's
   cap-height flush with its box top. So a column starting with a subtitle
   and a column starting with body text begin their text at the same
   y-coordinate.
   Chrome 133+ and Safari 17.4+ support this; older browsers ignore it
   (graceful degradation — the baseline rhythm grid still keeps subsequent
   lines aligned within a step or two). */
.panel-title,
.section-subtitle,
.narrative,
.partner-bio h3,
.partner-role,
.pricing-who,
.contact-co,
.faq-question {
  text-box-trim: trim-start;
  text-box-edge: cap alphabetic;
}

/* Desktop multi-column: NO trimming — one shared baseline grid instead.
   trim-start removes the leading above the first line of EVERY element.
   Two measured side effects in the side-by-side columns:
     1. Each trimmed paragraph pulled everything below it up ~6.7 px, so
        the offsets accumulated: body lines fell on 4–8 different phases of
        the 27.2 px rhythm, and neighbouring columns' lines did not line up.
     2. A paragraph CONTINUING into a new column is not trimmed (only an
        element's start is), so those columns began ~7 px lower than
        columns that start with a new paragraph.
   Untrimmed, every line-height and margin is a --rhythm multiple and 100 %
   of body lines share one grid (Leistungsangebot, Referenzen, Preise;
   only the portrait photos in Über uns break it). Mobile keeps the trim
   above — a single column has no neighbours to align with. */
@media (min-width: 769px) {
  .panel-title,
  .section-subtitle,
  .narrative,
  .partner-bio h3,
  .partner-role,
  .pricing-who,
  .contact-co,
  .faq-question {
    text-box-trim: none;
  }
  /* The 12 px + -12 px pair only existed to offset the trim; untrimmed,
     margin 0 keeps column 1 on the grid and the rule still starts exactly
     at the column top (= the nav-divider line top, 15vh). */
  .panel-title { margin-top: 0; }
  .panel-title::before { top: 0; }
  /* Untrimmed, subtitle text sits 6.7 px lower in its box (measured), so
     -3 px keeps the rule at the same distance above the glyphs as the
     previous calibrated -10 px did with trim. */
  .section-subtitle::before { top: -3px; }
  /* A subtitle that STARTS a column (flagged by alignColumnTops) must not
     overhang upwards: in multicol, anything above the column top is painted
     at the bottom of the PREVIOUS column — a stray stub of rule under its
     last line. Start it flush with the column top instead. */
  .section-subtitle[data-col-aligned]::before { top: 0; }
}

.narrative {
  font-size: 1rem;
  /* line-height matches --rhythm exactly so body lines fall on the baseline
     grid. 1.6 ratio at 17px = 27.2px = 1.6rem = --rhythm. */
  line-height: var(--rhythm);
  color: var(--body);
  /* margin-bottom = 1 rhythm step → exactly one blank line of grid space
     between paragraphs. (Previous 18px was 0.66 of a step, off-grid.) */
  margin-bottom: var(--rhythm);
  max-width: 65ch;
  text-align: left;
  /* text-wrap default (auto) — pretty/balance shortens columns */
  hyphens: auto;
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 16 8 6;
  -webkit-hyphenate-limit-chars: 16 8 6;
  hyphenate-limit-zone: 25%;
  hyphenate-limit-lines: 1;
  -webkit-hyphenate-limit-lines: 1;
  font-weight: 400;
}
.narrative strong { color: var(--ink-light); font-weight: 500; }
/* Proper names that auto-hyphenation would split mid-word
   ("RespectRese-archGroup"): only break at the &shy; given in the HTML. */
.hyphen-manual { hyphens: manual; -webkit-hyphens: manual; }

/* =========================================================
   PARTNER BIOS
   ========================================================= */
/* The bio is TALLER than one column (photo + name + focus + two long
   paragraphs + LinkedIn link), so it must fragment across columns —
   break-inside: avoid on the whole bio made it an unbreakable monolith
   whose lower half was CLIPPED by overflow: hidden (invisible text).
   Instead, only the bio's head (photo → name → role → focus) is kept
   together via break-after: avoid on each piece; the body paragraphs
   then flow across columns like every other narrative. */
.partner-bio { margin-bottom: var(--rhythm); }
.partner-photo {
  /* Full-column plate: the photo fills its entire column and is
     center-cropped via object-fit; the bio text starts in the next
     column. Column height = 100vh panel minus 2 × 15vh panel-content
     padding = 70vh (dvh companion in the @supports block below —
     percentage heights don't resolve inside multicol). */
  display: block;
  width: 100%;
  height: 70vh;
  object-fit: cover;
  margin: 0;
  /* In-text photos: mostly-grayscale silver-gelatin with a faint hint of
     real color coming through (grayscale 70% → 30% of the original hue),
     a whisper of warmth, full opacity. (This was the hover look the user
     chose to make permanent; no separate hover state now.) */
  filter: grayscale(70%) sepia(0.08);
  opacity: 1;
  border-radius: 2px;
  transition: filter 0.4s ease, opacity 0.4s ease;
  break-inside: avoid;
}
.partner-bio h3 {
  font-family: var(--serif); font-size: 1.3rem;
  font-weight: 400; color: var(--ink);
  letter-spacing: -0.02em; margin-bottom: 2px;
  break-after: avoid;
}
/* Role line: title flush left, LinkedIn link flush right, same baseline. */
.partner-role a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.3s ease;
}
.partner-role a:hover { color: var(--ink); }
.partner-role {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 0.58rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--mid);
  /* a full baseline unit below = one blank line before the bio text */
  margin-bottom: var(--rhythm);
  break-after: avoid;
}
.partner-quote {
  font-family: var(--serif); font-size: 1rem;
  font-style: italic; color: var(--muted); line-height: 1.65;
}

/* =========================================================
   SUB-CHAPTERS / SECTION BREAK
   ========================================================= */
/* Space ABOVE a section-break lives as margin-top on the section-break itself.
   This is critical for column filling: margin-top collapses to 0 when an
   element starts a fresh column, so it never leaves dead space at the bottom
   of the previous column. (Margin-bottom on the prior element was NOT trimmed
   reliably by Chrome at column breaks.)
   Values are exact multiples of --rhythm so the next element lands on grid. */
.section-break {
  /* 2 rhythm steps above (≈54.4px) gives a clear gap between sections.
     0 below — the subtitle inside has its own var(--rhythm) margin-bottom. */
  margin: calc(var(--rhythm) * 2) 0 0;
  padding-top: 0;
  clear: both;
  break-inside: avoid;
  break-after: avoid;
}
/* The very first section-break after the panel-title's own margin sits one
   rhythm closer so the spacing reads as "section gap" not "double gap". */
.panel-title ~ .section-group:first-of-type > .section-break:first-child {
  margin-top: var(--rhythm);
}
/* Reinforce orphan control via break-before on the immediately following sibling.
   This is theoretically redundant with `break-after: avoid` on .section-break, but
   some browsers honor only one direction; keep both for robustness. */
.section-break + .narrative,
.section-break + .partner-bio,
.section-break + .pillars,
.section-break + .faq-list,
.section-break + .contact-info,
.section-break + div,
.sub-chapter + .narrative,
.sub-chapter + div {
  break-before: avoid;
}
.section-group {
  /* no break-inside: avoid — allows natural column breaks within the group */
}
.section-break-title {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 2.2vw, 1.9rem);
  font-weight: 400; color: var(--ink);
  letter-spacing: -0.02em;
  /* 2 rhythm steps line-height keeps this larger heading on the baseline grid */
  line-height: calc(var(--rhythm) * 2);
  margin-bottom: var(--rhythm);
  border-top: 1px solid var(--line);
  padding-top: var(--rhythm);
  text-wrap: balance;
  break-after: avoid;
  hyphens: none;
}

/* =========================================================
   REFERENCES
   ========================================================= */
.ref-section { margin: var(--rhythm) 0; clear: both; }
.client-list {
  padding: 0 0 var(--rhythm);
  margin-bottom: 0;
}
/* =========================================================
   PRICING
   ========================================================= */
.pricing-grid {
  display: block; margin: 0 0 var(--rhythm); clear: both;
  /* keep both partners' fees in one column (never split Tilman from
     Niels across a column break) */
  break-inside: avoid;
}
.pricing-who {
  font-family: var(--serif); font-size: 1.15rem;
  font-weight: 400; color: var(--ink);
  margin-bottom: 4px; letter-spacing: -0.015em;
  margin-top: 16px;
}
.pricing-grid > div { break-inside: avoid; }
/* Pricing rows use the regular paragraph (sans) font at 1rem — same as
   .narrative body text — so the actual fee labels and values read like
   normal copy rather than a stylised price table. */
.pricing-row {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 7px 0;
  font-family: var(--sans);
  font-size: 1rem;
  color: var(--body);
  line-height: var(--rhythm);
}
.pricing-val {
  font-family: var(--sans); font-size: 1rem;
  color: var(--ink); letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Desktop: set the fee table on the baseline grid. The 16/4/7 px spacing
   was off-grid and made the block 251 px tall, so "Tagessätze" no longer
   fit under the intro in column 1 below a ~865 px window and slid into
   column 2. One --rhythm line per name/row and one blank line between the
   partners: ~190 px, on-grid, fits column 1 down to ~780 px. */
@media (min-width: 769px) {
  .pricing-who {
    line-height: var(--rhythm);
    margin: var(--rhythm) 0 0;
  }
  .pricing-grid > div:first-child .pricing-who { margin-top: 0; }
  .pricing-row { padding: 0; }
}

/* =========================================================
   CONTACT
   ========================================================= */
.contact-co {
  font-family: var(--serif); font-size: 1.35rem;
  font-weight: 400; color: var(--ink);
  margin-bottom: 4px; letter-spacing: -0.02em;
  break-after: avoid;
}
.contact-info p { font-size: 0.92rem; line-height: 1.6; color: var(--body); }
.rule-sm { width: 24px; height: 1px; background: var(--line); margin: 10px 0; }
a { color: var(--ink-light); text-decoration: none; transition: color 0.3s ease; }
a:hover { color: var(--ink); }

/* Client-list links: same ink as the surrounding running text, marked only
   by a whisper-thin underline so linked and unlinked names sit calmly in the
   same comma-separated line. Underline warms/darkens slightly on hover. */
.client-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--faint);
  text-decoration-thickness: 0.5px;
  text-underline-offset: 2px;
  transition: color 0.3s ease, text-decoration-color 0.3s ease;
}
.client-link:hover { color: var(--ink); text-decoration-color: var(--mid); }
/* =========================================================
   CONTACT FORM — Kontakt section
   The Kontakt panel uses the same multi-column layout as the other
   four sections (column-width: 320 inherited from .panel-content).
   Clean column structure:
     col 1: panel-title + intro narrative
     col 2: contact-form-wrap (Emailformular subtitle + form)
     col 3: cf-address (Adresse subtitle + contact info)
   Both blocks are kept atomic via break-inside: avoid so neither splits
   awkwardly across columns. The form's column break is set via inline
   style; Adresse's via the rule below. */
.contact-form-wrap { display: block; }
#contact-form { break-inside: avoid; display: block; }
.cf-address {
  break-inside: avoid;
  break-before: column;
}
/* Side-by-side Name + Organisation on the form's first row, saving one
   full input's vertical space so form + Adresse can share column 2. */
.form-row {
  display: flex;
  /* matches the page's column gap — side-by-side fields read as
     separate columns */
  gap: 48px;
}
.form-row > .form-group { flex: 1 1 0; min-width: 0; }
.form-group { margin-bottom: 20px; }
.form-group label {
  display: block; font-family: var(--sans); font-size: 0.92rem;
  font-weight: 400; letter-spacing: normal; text-transform: none;
  color: var(--mid); margin-bottom: 3px;
}
.form-group input, .form-group select, .form-group textarea {
  width: 100%; padding: 4px 0; font-family: var(--serif);
  font-size: 1rem; color: var(--ink-light);
  background: transparent; border: none;
  border-bottom: 1px solid var(--line);
  outline: none; transition: border-color 0.3s ease;
  border-radius: 0; -webkit-appearance: none;
  min-height: 36px;
}
.form-group input:focus, .form-group select:focus, .form-group textarea:focus { border-bottom-color: var(--ink); }
.form-group textarea { resize: vertical; min-height: 225px; }
.form-group select { cursor: pointer; }
/* In-field labels: the field names sit inside the fields as placeholder
   text (the real <label>s are sr-only for assistive tech) and disappear
   as the sender types over them. */
.form-group input::placeholder,
.form-group textarea::placeholder {
  color: var(--muted);
  opacity: 1;   /* Firefox dims placeholders by default */
}
/* The select shows its in-field label ("Anlass – bitte wählen…") in the
   same muted tone until a real option is chosen. */
.form-group select:has(option[value=""]:checked) {
  color: var(--muted);
}
.btn-submit {
  font-family: var(--sans); font-size: 0.6rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-light); background: transparent;
  border: 1px solid var(--line); padding: 10px 40px;
  cursor: pointer; transition: all 0.3s ease; margin-top: 4px;
  width: 100%; display: block;
  break-before: avoid;
}
/* Hover stays in the brand creme palette — same darker-creme treatment
   as the active divider, not the full ink black. */
.btn-submit:hover,
.btn-submit:focus-visible {
  background: var(--bg-dark);
  color: var(--ink);
  border-color: var(--bg-dark);
}
/* Send result under the button — visible to everyone (was screen-reader
   only, so sighted visitors never saw errors or the fallback address).
   Quiet body-text styling; empty = takes no space. */
.cf-status {
  font-family: var(--sans); font-size: 0.8rem; line-height: var(--rhythm);
  color: var(--body); margin: 8px 0 0;
}
.cf-status:empty { display: none; }
.cf-status a { color: inherit; text-decoration: underline; text-decoration-color: var(--faint); }

/* =========================================================
   FAQ
   ========================================================= */
.faq-list { margin: 8px 0 20px; }
.faq-item {
  padding: 12px 0;
  border-top: 1px solid var(--line-light);
  break-inside: avoid;
}
.faq-question {
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 400;
  color: var(--body);
  line-height: 1.6;
  letter-spacing: normal;
}

/* =========================================================
   FOOTER BAR
   ========================================================= */
.site-footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  padding: 24px 24px 12px;
  background: linear-gradient(to top, var(--bg) 35%, rgba(245,244,241,0.7) 60%, transparent);
  pointer-events: none;
}
.footer-links, .footer-social {
  display: flex;
  gap: 16px;
  align-items: center;
  pointer-events: auto;
}
.footer-logo {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 10px;
  opacity: 0;
  transition: opacity 0.6s ease;
  pointer-events: none;
}
.bookshelf.has-active ~ .site-footer .footer-logo {
  opacity: 1;
  pointer-events: auto;
}
.footer-wordmark {
  font-family: var(--serif);
  font-size: 0.9rem;
  font-weight: 300;
  letter-spacing: 0.04em;
  color: var(--ink-light);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: color 0.3s ease;
}
.footer-wordmark:hover {
  color: var(--ink);
}
.footer-link {
  font-family: var(--sans);
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px 0;
  transition: color 0.3s ease;
}
.footer-link:hover { color: var(--ink); }
.footer-social a {
  color: var(--muted);
  transition: color 0.3s ease;
  display: flex;
  align-items: center;
}
.footer-social a:hover { color: var(--ink); }

/* =========================================================
   MODALS
   ========================================================= */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(26, 25, 24, 0.5);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  /* visibility: hidden removes the (opacity-0) modal's buttons and links
     from the keyboard tab order while closed. The delayed visibility
     transition keeps the fade-out animation visible. */
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}
.modal-overlay.open {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: opacity 0.3s ease;
}
/* The two literal colours above, read in Display-P3 like the palette
   (see the @supports block after :root). Placed after both rules so it
   wins; the mobile footer later resets its background to var(--bg). */
@supports (color: color(display-p3 0 0 0)) {
  .site-footer {
    background: linear-gradient(to top, var(--bg) 35%, color(display-p3 0.9608 0.9569 0.9451 / 0.7) 60%, transparent);
  }
  .modal-overlay { background: color(display-p3 0.1020 0.0980 0.0941 / 0.5); }
}
.modal-content {
  background: var(--bg);
  max-width: 600px;
  width: 90%;
  max-height: 80vh;
  overflow-y: auto;
  padding: 48px;
  position: relative;
  transform: translateY(20px);
  transition: transform 0.3s ease;
}
.modal-overlay.open .modal-content {
  transform: translateY(0);
}
.modal-close {
  position: sticky;
  top: 0;
  float: right;
  z-index: 2;
  font-size: 1.6rem;
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  line-height: 1;
  transition: color 0.3s ease;
  margin: -8px -8px 0 0;
}
.modal-close:hover { color: var(--ink); }
.modal-content h2 {
  font-family: var(--serif);
  font-size: clamp(1.4rem, 2.2vw, 1.8rem);
  font-weight: 300;
  font-style: italic;
  color: var(--ink);
  letter-spacing: -0.02em;
  margin-bottom: 20px;
}
.modal-content h3 {
  font-family: var(--serif);
  font-size: 1.1rem;
  font-weight: 400;
  color: var(--ink);
  margin-top: 20px;
  margin-bottom: 6px;
}
.modal-content p {
  font-size: 0.88rem;
  line-height: 1.8;
  color: var(--mid);
  margin-bottom: 10px;
}

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (max-width: 1100px) {
  :root { --divider-w: 26px; }
  .panel-content { padding: 15vh 32px; }
}
@media (max-width: 900px) {
  :root { --divider-w: 24px; }
  .divider-label { font-size: 0.9rem; }
  .panel-content { padding: 15vh 28px; column-width: 280px; column-gap: 36px; }
  .form-row { display: block; }
  .hero-inner { min-width: 280px; }
  .hero-wordmark { font-size: clamp(3rem, 9vw, 5rem); }
  .hero-def { padding: 32px; }
  .def-text { font-size: 0.78rem; }
}
/* Wide desktop — restore the proportions designed at ~1400 px: wider
   columns and divider strips so the layout doesn't feel sparse on
   large monitors. */
@media (min-width: 1600px) {
  :root { --divider-w: 44px; }
  .panel-content { column-width: 360px; column-gap: 56px; }
}
/* Dynamic viewport units — on mobile browsers 100vh includes the
   collapsing address bar, causing overflow and misaligned 15vh-anchored
   divider lines. dvh tracks the actually-visible viewport. All 15vh
   paddings must switch together: the heading/nav line alignment assumes
   panel padding-top and divider line-top use the same unit. */
@supports (height: 100dvh) {
  body { height: 100dvh; }
  .bookshelf { height: 100dvh; }
  .bookshelf.has-active .logo-mark { padding: 15dvh 0; }
  .bookshelf.has-active .divider,
  .bookshelf.nav-revealed .divider { padding: 15dvh 0; }
  .panel-content { padding-top: 15dvh; padding-bottom: 15dvh; }
  .panel-bg { top: 15dvh; height: calc(100% - 30dvh); }
  .partner-photo { height: 70dvh; }
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.15s !important;
  }
}

/* =========================================================
   KEYBOARD FOCUS — :focus-visible only, so mouse users don't see rings
   ========================================================= */
:where(.divider, .logo-mark, .footer-link, .footer-wordmark,
       .modal-close, .btn-submit, .form-group input, .form-group select,
       .form-group textarea, .panel-scroll, a):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  /* Prevent the outline from being clipped by ancestors */
  position: relative;
  z-index: 5;
}
.divider:focus-visible,
.logo-mark:focus-visible {
  /* These elements are narrow strips — offset INWARD so the ring stays
     visible within the strip rather than being cut off by neighbors. */
  outline-offset: -2px;
}
.panel-scroll:focus-visible {
  /* The scroll area becomes focusable when keyboard nav lands on it.
     Use a soft inset ring to avoid double-bordering the panel edges. */
  outline-offset: -4px;
}
/* Footer social icon links: shrink to fit the SVG */
.footer-social a:focus-visible {
  outline-offset: 4px;
  border-radius: 3px;
}

/* =========================================================
   MOBILE LAYOUT — vertical scroll instead of horizontal bookshelf.
   On screens ≤ 768 px wide we abandon the desktop multi-column
   bookshelf metaphor entirely. The page becomes a normal vertical
   scroll: hero → divider label → section → divider label → section
   ... with a hamburger menu in the top-right for quick anchor jumps.
   ========================================================= */
@media (max-width: 768px) {
  /* --- Unlock the document from its full-height locked state --- */
  html, body {
    height: auto;
    overflow-x: hidden;
    overflow-y: auto;
  }
  body { padding-bottom: 96px; } /* room for fixed footer */

  /* --- Hide the desktop-only flair --- */
  #lines-canvas { display: none; }
  .logo-mark { display: none; }
  .scroll-cue { display: none; }

  /* --- Bookshelf becomes a vertical stack --- */
  .bookshelf {
    display: block;
    height: auto;
    overflow: visible;
    position: static;
  }

  /* --- Hero panel: full viewport, centred --- */
  .hero-panel {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    padding: 64px 24px 48px;
    grid-template-rows: none;
  }
  .hero-inner { position: static; min-width: 0; width: 100%; max-width: 480px; }
  .hero-wordmark {
    font-size: clamp(3rem, 14vw, 5rem);
    transform: none;
  }
  .hero-tagline {
    position: static; transform: none; left: auto; top: auto;
    text-align: center;
    margin-top: 24px;
    font-size: clamp(1rem, 4vw, 1.2rem);
    opacity: 1;
  }
  .hero-def {
    position: static; transform: none; left: auto; top: auto;
    max-width: 480px;
    margin: 32px auto 0;
    padding: 24px;
    opacity: 1;
    text-align: left;
  }
  .def-text { font-size: 0.85rem; }
  /* No clever positioning on .bookshelf.spines-visible / .has-active states */
  .bookshelf.has-active .hero-wordmark,
  .bookshelf.has-active .hero-tagline,
  .bookshelf.has-active .hero-def,
  .bookshelf.spines-visible .hero-wordmark,
  .bookshelf.spines-visible .hero-tagline,
  .bookshelf.spines-visible .hero-def {
    transform: none;
    opacity: 1;
    pointer-events: auto;
  }

  /* --- Dividers become horizontal section bars that visually echo the
         desktop's vertical divider stripes (only rotated 90°).
         The desktop divider has a thin VERTICAL line cropped to the middle
         70% (via border-image with `to bottom` gradient at 15%–85%).
         Here we use the SAME gradient with `to right` so the thin line runs
         HORIZONTALLY across the middle 70% of the width — a direct mirror. */
  .divider {
    width: 100%;
    min-height: auto;
    height: auto;
    padding: 28px 24px 24px;
    margin: 0;
    background: var(--bg);
    border: none;
    border-image: linear-gradient(to right, transparent 15%, var(--ink) 15%, var(--ink) 85%, transparent 85%) 1;
    border-top-width: 1px;
    border-top-style: solid;
    flex: none;
    display: block;
    text-align: center;
    cursor: default; /* it's a section label on mobile, not a button */
    pointer-events: none;
  }
  /* Label sits horizontally in the brand serif italic — same typographic
     identity as the desktop divider, just oriented horizontally. */
  .divider-label {
    writing-mode: horizontal-tb;
    text-orientation: mixed;
    transform: none;
    font-family: var(--serif);
    font-style: italic;
    font-weight: 400;
    font-size: 1.05rem;
    letter-spacing: 0.02em;
    text-transform: none;
    color: var(--ink);
    white-space: normal;
    display: block;
  }
  .divider.active,
  .divider.passed,
  .divider:hover { background: var(--bg); }
  .divider.active .divider-label,
  .divider:hover .divider-label { color: var(--ink); }

  /* --- Panels: always visible, stacked, single-column --- */
  .panel {
    flex: none;
    width: 100%;
    height: auto;
    min-height: auto;
    overflow: visible;
    background: transparent;
    position: relative;
    transition: none;
  }
  .panel.active,
  .bookshelf.has-active .panel {
    flex-grow: 0;
    transition: none;
  }
  .panel::after { display: none; } /* no panel cover */
  .panel-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    top: 0; right: 0; bottom: 0; left: 0;
    opacity: 0.08;
    transform: none;
    mask-image: linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
  }
  .panel.active.revealed .panel-bg,
  .panel .panel-bg { opacity: 0.08; transform: none; }

  .panel-scroll {
    height: auto;
    overflow: visible;
    opacity: 1;
    transform: none;
    transition: none;
    mask-image: none;
    -webkit-mask-image: none;
  }
  .panel.active.revealed .panel-scroll {
    opacity: 1;
    transform: none;
    mask-image: none;
    -webkit-mask-image: none;
  }

  /* --- Panel content: single column, normal vertical flow --- */
  .panel-content {
    height: auto;
    padding: 24px 24px 64px;
    column-width: auto;
    column-count: 1;
    column-gap: 0;
    column-fill: auto;
    max-width: 640px;
    margin: 0 auto;
  }
  .panel-spacer { display: none; } /* no horizontal scroll, no spacer */
  /* All explicit column-break overrides from the HTML stop applying */
  .panel-content [style*="break-before: column"] {
    break-before: auto !important;
  }

  /* --- Panel title: smaller, single-line rhythm, less margin --- */
  .panel-title {
    font-size: clamp(1.4rem, 5.5vw, 1.7rem);
    line-height: var(--rhythm);
    margin-top: 8px;
    margin-bottom: var(--rhythm);
  }
  .panel-title::before {
    top: -6px;
    bottom: 2px;
  }
  /* Subtitles: a bit tighter on mobile */
  .section-subtitle {
    font-size: clamp(1rem, 4.5vw, 1.15rem);
    margin-top: var(--rhythm);
  }

  /* --- Contact form on mobile: stays vertical, natural sizing --- */
  .contact-form-wrap { display: block; }
  #contact-form { display: block; }
  #contact-form textarea { min-height: 120px; resize: vertical; }

  /* --- Pricing grid: stack the two partner blocks --- */
  .pricing-grid { display: block; }

  /* --- Partner bios: keep break-inside avoid removed since no columns --- */
  .partner-bio { break-inside: auto; margin-bottom: calc(var(--rhythm) * 2); }
  /* natural photo height in the vertical flow (desktop full-column crop
     doesn't apply without columns) */
  /* Both portraits share one 4:5 plate so a landscape and a tall
     original look like a matched pair; object-position keeps each face
     in the upper third of the crop. */
  .partner-photo {
    width: 100%;
    max-width: 320px;
    height: auto;
    aspect-ratio: 4 / 5;
    object-fit: cover;
    margin-bottom: var(--rhythm);
  }
  .partner-photo[src$="partner-eckloff.jpeg"] { object-position: 45% 50%; }
  .partner-photo[src$="partner-quaquebeke.jpeg"] { object-position: 50% 40%; }

  /* --- Footer: stack vertically --- */
  .site-footer {
    position: relative;
    flex-direction: column;
    gap: 16px;
    padding: 32px 24px;
    background: var(--bg);
    border-top: 1px solid rgba(26, 25, 24, 0.08);
  }
  .footer-links, .footer-logo, .footer-social {
    width: 100%;
    text-align: center;
    justify-content: center;
  }

  /* --- HAMBURGER BUTTON (fixed top-right) --- */
  .mobile-nav-toggle {
    position: fixed;
    top: 16px;
    right: 16px;
    width: 44px;
    height: 44px;
    background: var(--bg);
    border: 1px solid rgba(26, 25, 24, 0.15);
    border-radius: 4px;
    z-index: 1100;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 5px;
    cursor: pointer;
    padding: 0;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
  }
  .mobile-nav-toggle span {
    display: block;
    width: 22px;
    height: 1.5px;
    background: var(--ink);
    transition: transform 0.3s ease, opacity 0.3s ease;
    transform-origin: center;
  }
  .mobile-nav-toggle[aria-expanded="true"] {
    border-color: var(--ink);
  }
  .mobile-nav-toggle[aria-expanded="true"] span:nth-child(1) {
    transform: translateY(6.5px) rotate(45deg);
  }
  .mobile-nav-toggle[aria-expanded="true"] span:nth-child(2) {
    opacity: 0;
  }
  .mobile-nav-toggle[aria-expanded="true"] span:nth-child(3) {
    transform: translateY(-6.5px) rotate(-45deg);
  }

  /* --- HAMBURGER OVERLAY MENU --- */
  .mobile-menu {
    position: fixed;
    inset: 0;
    background: var(--bg);
    z-index: 1090;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 24px;
    padding: 80px 32px 32px;
    transform: translateY(-100%);
    transition: transform 0.4s cubic-bezier(0.25, 0.1, 0.25, 1);
    visibility: hidden;
  }
  .mobile-menu[aria-hidden="false"] {
    transform: translateY(0);
    visibility: visible;
  }
  .mobile-menu a {
    font-family: var(--serif);
    font-style: italic;
    font-size: clamp(1.4rem, 7vw, 1.8rem);
    color: var(--ink);
    text-decoration: none;
    padding: 8px 16px;
    transition: opacity 0.2s ease;
  }
  .mobile-menu a:hover,
  .mobile-menu a:focus-visible {
    opacity: 0.6;
  }

  /* --- Modals on mobile: full screen --- */
  .modal-content {
    max-width: 100%;
    max-height: 90vh;
    margin: 16px;
    padding: 24px;
  }

  /* --- Subtle reveal-on-scroll animation for dividers + first paragraph
        Initial state: slightly translated and faded;
        .in-view (added by IntersectionObserver) restores normal state. --- */
  .divider, .panel-content {
    opacity: 1; /* default = visible (in case JS doesn't run) */
  }
  /* Allow JS to opt-in by adding .reveal-on-scroll, then .in-view */
  .reveal-on-scroll {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.6s ease, transform 0.6s ease;
  }
  .reveal-on-scroll.in-view {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Hide mobile nav on desktop */
@media (min-width: 769px) {
  .mobile-nav-toggle, .mobile-menu {
    display: none !important;
  }
}

/* =========================================================
   PRINT — flatten the horizontal-scrolling bookshelf into a stacked,
   single-column document so any visible content can be printed cleanly.
   ========================================================= */
@media print {
  html, body {
    height: auto;
    overflow: visible;
    background: #fff;
    color: #000;
    font-size: 11pt;
    line-height: 1.5;
  }
  /* Hide all the interactive scaffolding */
  #lines-canvas,
  .divider,
  .logo-mark,
  .scroll-cue,
  .site-footer,
  .modal-overlay,
  .panel-bg,
  .panel::after,
  .hero-def {
    display: none !important;
  }
  /* Bookshelf becomes a normal document flow */
  .bookshelf {
    display: block !important;
    height: auto !important;
    overflow: visible !important;
  }
  /* Hero block: wordmark + tagline at the top, like a cover */
  .hero-panel {
    display: block !important;
    height: auto !important;
    padding: 24pt 0 !important;
    text-align: center;
    page-break-after: always;
  }
  .hero-inner { display: block; }
  .hero-wordmark {
    font-size: 36pt;
    margin-bottom: 8pt;
    transform: none !important;
    opacity: 1 !important;
  }
  .hero-tagline {
    position: static !important;
    font-size: 14pt;
    transform: none !important;
    opacity: 1 !important;
  }
  /* Each panel renders as a stacked section, full width */
  .panel {
    display: block !important;
    flex: none !important;
    height: auto !important;
    overflow: visible !important;
    page-break-before: always;
    page-break-inside: auto;
  }
  .panel-scroll {
    height: auto !important;
    overflow: visible !important;
    opacity: 1 !important;
    transform: none !important;
    mask-image: none !important;
    -webkit-mask-image: none !important;
  }
  .panel-content {
    height: auto !important;
    padding: 0 !important;
    column-count: 1 !important;
    column-width: auto !important;
    display: block !important;
  }
  .panel-spacer { display: none !important; }
  /* Keep typography readable in print, drop italics on titles for legibility */
  .panel-title {
    font-size: 18pt;
    margin-top: 0;
    margin-bottom: 8pt;
    page-break-after: avoid;
  }
  .section-subtitle {
    font-size: 13pt;
    margin-bottom: 4pt;
    page-break-after: avoid;
  }
  .narrative {
    font-size: 10.5pt;
    margin-bottom: 6pt;
    orphans: 3;
    widows: 3;
  }
  /* Render partner photos in grayscale at a reasonable size */
  .partner-photo {
    max-width: 200pt;
    height: auto;
    filter: grayscale(100%);
    page-break-inside: avoid;
  }
  .partner-bio { page-break-inside: avoid; }
  .pricing-grid > div { page-break-inside: avoid; }
  /* Ensure links are usable: show the URL after each external link */
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 9pt;
    color: #555;
  }
  /* Hide form including its "Emailformular" subtitle — printing a
     contact form is not useful, and the bare heading would float. */
  .contact-form-wrap { display: none !important; }
}
