/* ==========================================================================
   Friseur am Eck - tokens
   ========================================================================== */

/* Self-hosted, not loaded live from Google Fonts (2026-09-11): serving
   Google Fonts directly from fonts.googleapis.com/fonts.gstatic.com sends
   every visitor's IP address to Google before they've agreed to anything,
   which is the exact pattern German courts (LG Munich, 2022) and DPAs have
   flagged as a GDPR violation. Both files are the variable-font builds
   Google itself serves (one file per family, weight is an axis rather than
   a separate file per cut), so this covers every weight this project uses
   without needing per-weight files. */
@font-face {
  font-family: "Baloo 2";
  src: url("fonts/Baloo2-Variable.woff2") format("woff2-variations"), url("fonts/Baloo2-Variable.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Work Sans";
  src: url("fonts/WorkSans-Variable.woff2") format("woff2-variations"), url("fonts/WorkSans-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* palette, sampled from the salon's own walls and its storefront sign;
     plum is the exact brand purple from the client's original logo files
     (CMYK 60/80/0/0) */
  --cream: #f8f4ef;
  --cream-deep: #f0e9e1;
  --ink: #26201d;
  --ink-soft: #5c4f47;
  --mauve: #e9d9d6;
  --mauve-deep: #8c6d6c;
  --sage: #bfd0ca;
  --sage-deep: #49635c;
  --wood: #c39a6c;
  --plum: #663399;
  --plum-deep: #4c2672;
  --plum-tint: #ece6f2;
  --line: rgba(38, 32, 29, 0.14);
  --line-soft: rgba(38, 32, 29, 0.08);

  /* fixed, does not change with the theme: text/icons sitting on the
     always-dark plum surface (buttons, skip link, footer) need to stay
     light in both themes, independent of the page background token */
  --on-plum: #f8f4ef;

  --font-display: "Baloo 2", "Arial Rounded MT Bold", "Arial Narrow", sans-serif;
  --font-body: "Work Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 24px;
  --radius-pill: 999px;

  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);

  --dur-fast: 160ms;
  --dur-base: 240ms;
  --dur-slow: 460ms;

  --nav-h: 76px;
  --container: 1280px;

  color-scheme: light;
}

/* Dark theme: opt-in only, via the toggle in the nav. The page defaults to
   light regardless of system preference (per explicit user instruction) and
   only switches when data-theme="dark" is set on the root by script.js. */
:root[data-theme="dark"] {
  --cream: #1c1815;
  --cream-deep: #262019;
  --ink: #f2ece5;
  --ink-soft: #b7aca3;
  --mauve: #362a29;
  --mauve-deep: #a3827e;
  --sage: #212a20;
  --sage-deep: #9cba8d;
  --wood: #d6b389;
  --plum: #663399;
  --plum-deep: #7b3db8;
  --plum-tint: rgba(160, 113, 208, 0.28);
  --line: rgba(255, 255, 255, 0.14);
  --line-soft: rgba(255, 255, 255, 0.08);

  color-scheme: dark;
}

/* ==========================================================================
   Reset
   ========================================================================== */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 12px);
  max-width: 100%;
  overflow-x: clip;
}

body {
  margin: 0;
  max-width: 100%;
  overflow-x: clip;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Remove the legacy mobile tap delay and make taps win immediately over
   browser gesture heuristics. This is especially important for the two
   full-card links to the price pages. */
a,
button { touch-action: manipulation; }

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, dl { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, p { margin: 0; }
address { font-style: normal; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
input, textarea { font: inherit; color: inherit; }

::selection { background: var(--plum); color: var(--on-plum); }

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

/* custom scrollbar, themed rather than left as a browser default */
html { scrollbar-color: var(--mauve-deep) var(--cream-deep); scrollbar-width: thin; }
::-webkit-scrollbar { width: 12px; }
::-webkit-scrollbar-track { background: var(--cream-deep); }
::-webkit-scrollbar-thumb { background: var(--mauve-deep); border-radius: var(--radius-pill); border: 3px solid var(--cream-deep); }

.skip-link {
  position: absolute;
  left: 1rem;
  top: 1rem;
  background: var(--plum);
  color: var(--on-plum);
  padding: 0.75rem 1.25rem;
  border-radius: var(--radius-sm);
  z-index: 200;
  transform: translateY(-150%);
  transition: transform var(--dur-base) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

.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;
}

/* ==========================================================================
   Type
   ========================================================================== */

h1, h2 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 0.96;
  text-wrap: balance;
}

.hero-headline { font-size: clamp(2.75rem, 6vw, 5rem); }
section h2 { font-size: clamp(2.75rem, 5.6vw, 4.6rem); color: var(--ink); }

p { max-width: 62ch; }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.95rem 1.8rem;
  /* One squared-off corner (top-left) on an otherwise fully pilled
     button, on every button in the system: a deliberate signature
     detail, not a rounding bug. */
  border-radius: 0 var(--radius-pill) var(--radius-pill) var(--radius-pill);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.98rem;
  white-space: nowrap;
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}

.btn-primary {
  background: var(--plum);
  color: var(--on-plum);
  box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset, 0 10px 24px -12px rgba(75,31,99,0.55);
}
.btn-primary:hover { background: var(--plum-deep); }
.btn-primary:active { transform: scale(0.97); }

.btn-block { width: 100%; }

/* ==========================================================================
   Navigation
   ========================================================================== */

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--cream);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

.nav[data-scrolled] {
  border-bottom-color: var(--line);
  box-shadow: 0 8px 24px -20px rgba(38,32,29,0.4);
}

/* Three-column grid, not a flex row: a flex row with nav-links pushed
   right via margin-left:auto only ever sits next to the logo, never
   centered in the bar. The grid's two 1fr edge columns (logo, actions)
   stay roughly balanced in width, so the auto-width center column
   (nav-links) lands genuinely centered between them. When nav-links is
   display:none on mobile, that center column just collapses to 0
   width; logo and actions still land correctly at the two edges. */
.nav-inner {
  max-width: var(--container);
  margin: 0 auto;
  height: var(--nav-h);
  padding: 0 clamp(1.25rem, 4vw, 2.5rem);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
}

.logo { flex-shrink: 0; color: var(--ink); display: flex; align-items: center; justify-self: start; }
.logo-fallback {
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
}

/* Traced directly from the client's original vector logo files
   (Friseur am Eck.svg): one fused path for the letterforms (currentColor,
   so nav vs. footer text color applies automatically) plus the two
   corner-flag accents as a separate path in the brand purple. Inlined in
   full in both nav and footer (not shared via <symbol>/<use>): a <use>
   sprite's referenced content sits in a shadow-like instance tree that
   external descendant selectors (e.g. ".footer-logo .brandmark-mark")
   cannot reach, which silently broke the footer's wood-colored mark
   override the first time this was tried. */
.brandmark { display: block; height: 1.6rem; width: auto; }
.brandmark-ink { fill: currentColor; }
.brandmark-mark { fill: var(--plum); }

.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2rem);
  justify-self: center;
  font-size: 0.95rem;
  font-weight: 500;
}

.nav-links a { position: relative; padding: 0.3rem 0; color: var(--ink-soft); transition: color var(--dur-fast) var(--ease-out); }
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 1.5px;
  background: var(--plum);
  transition: right var(--dur-base) var(--ease-out);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a:hover::after { right: 0; }

.nav-actions {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 1.5rem);
  justify-self: end;
}

.nav-cta { flex-shrink: 0; padding: 0.7rem 1.4rem; font-size: 0.92rem; }

.theme-toggle {
  position: relative;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 0 var(--radius-pill) var(--radius-pill) var(--radius-pill);
  color: var(--ink-soft);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.theme-toggle:hover { background: var(--cream-deep); color: var(--ink); }
.theme-toggle:active { transform: scale(0.93); }

.theme-icon {
  position: absolute;
  width: 20px;
  height: 20px;
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.theme-icon--moon { opacity: 1; transform: scale(1) rotate(0deg); }
.theme-icon--sun { opacity: 0; transform: scale(0.7) rotate(-40deg); }
:root[data-theme="dark"] .theme-icon--moon { opacity: 0; transform: scale(0.7) rotate(40deg); }
:root[data-theme="dark"] .theme-icon--sun { opacity: 1; transform: scale(1) rotate(0deg); }

.nav-toggle {
  display: none;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 0 var(--radius-pill) var(--radius-pill) var(--radius-pill);
  transition: transform var(--dur-fast) var(--ease-out);
}
.nav-toggle:active { transform: scale(0.93); }

.nav-toggle-box { position: relative; width: 20px; height: 14px; }
.nav-toggle-box span {
  position: absolute;
  top: 6px;
  left: 0; right: 0;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform var(--dur-base) var(--ease-in-out), opacity var(--dur-fast) var(--ease-out);
}
.nav-toggle-box span:nth-child(1) { transform: translateY(-6px); }
.nav-toggle-box span:nth-child(2) { transform: translateY(0); }
.nav-toggle-box span:nth-child(3) { transform: translateY(6px); }

.nav-toggle[aria-expanded="true"] .nav-toggle-box span:nth-child(1) { transform: translateY(0) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-box span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-box span:nth-child(3) { transform: translateY(0) rotate(-45deg); }

.mobile-nav {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-in-out);
  border-bottom: 1px solid transparent;
  background: var(--cream);
}
.mobile-nav[data-open] {
  grid-template-rows: 1fr;
  border-bottom-color: var(--line);
}
.mobile-nav-inner {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0 clamp(1.25rem, 4vw, 2.5rem);
}
.mobile-nav[data-open] .mobile-nav-inner { padding-bottom: 1.5rem; }
.mobile-nav-inner a {
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line-soft);
  font-weight: 500;
}
.mobile-nav-inner .btn { margin-top: 1rem; }

/* ==========================================================================
   Hero
   - Full-bleed editorial photograph, not a boxed image beside text. The
     photo IS the hero; type sits directly on it, bottom-left, where the
     source photograph is already soft and out of focus so the scrim only
     has to deepen an existing quiet, not fight a busy one.
   ========================================================================== */

.hero {
  position: relative;
  min-height: calc(100dvh - var(--nav-h));
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--plum-deep);
}

.hero-media { position: absolute; inset: 0; z-index: 0; }

.hero-bg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 22% 42%;
  display: block;
  opacity: 1;
  transform: scale(1);
}
html.js-reveal .hero-bg {
  opacity: 0;
  transform: scale(1.08);
  transition: opacity 900ms var(--ease-out), transform 1600ms var(--ease-out);
}
html.js-reveal .hero-bg.is-visible { opacity: 1; transform: scale(1); }

/* Tinted to the brand's plum, not a generic black scrim: dark and legible
   over the left third where the headline sits, clear by the right third
   where the photograph's own subject should read undimmed. */
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(100deg, rgba(55, 23, 74, 0.90) 0%, rgba(55, 23, 74, 0.68) 26%, rgba(55, 23, 74, 0.22) 50%, rgba(55, 23, 74, 0.02) 66%, transparent 78%),
    linear-gradient(0deg, rgba(55, 23, 74, 0.5) 0%, rgba(55, 23, 74, 0) 32%);
  pointer-events: none;
}

.hero-inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: clamp(2rem, 6vw, 4rem) clamp(1.25rem, 4vw, 2.5rem) clamp(3rem, 8vw, 5.5rem);
}

.hero-content {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 34rem;
  margin-left: clamp(2.5rem, 5vw, 4.5rem);
  color: var(--on-plum);
}

.hero-corner {
  position: absolute;
  top: clamp(-3rem, -4vw, -2rem);
  left: clamp(-3.25rem, -4vw, -2.25rem);
  width: clamp(5.5rem, 9vw, 8rem);
  height: clamp(5.5rem, 9vw, 8rem);
  color: var(--mauve);
  opacity: 0.82;
  pointer-events: none;
}

.hero-corner svg { width: 100%; height: 100%; }

.hero-headline { color: var(--on-plum); }

/* Line-mask reveal: each line rides up out of an overflow-hidden mask
   instead of just fading, so the headline arrives like a considered
   editorial title card rather than a bullet list settling into place. */
.line-mask { display: block; overflow: hidden; }
.hero-line { display: block; opacity: 1; transform: none; filter: none; }
html.js-reveal .hero-line {
  opacity: 0;
  transform: translateY(105%);
  filter: blur(6px);
  transition: opacity var(--dur-slow) var(--ease-out), transform 720ms var(--ease-out), filter var(--dur-slow) var(--ease-out);
}
html.js-reveal .hero-line.is-visible { opacity: 1; transform: translateY(0); filter: blur(0); }

.hero-sub {
  margin-top: 1.5rem;
  font-size: 1.1rem;
  color: rgba(248, 244, 239, 0.86);
  max-width: 34ch;
}

.hero-content .btn { margin-top: 2.25rem; }

/* ==========================================================================
   Philosophy
   ========================================================================== */

.philosophy { position: relative; background: var(--mauve); overflow: hidden; }

/* A single oversized ghost of the sign's own bracket glyph, bleeding off
   the top-right corner: texture and brand-provenance rather than a stock
   icon, and quiet enough not to compete with the type sitting over it.
   `top` stays small on purpose: the glyph's corner joint sits near the
   TOP of its own viewBox (path starts at y=5 of 34), so at this box size
   (up to 20rem) a `-8vw`-scale negative top offset pushes that joint
   above the section's overflow:hidden boundary and clips away the
   horizontal stroke entirely, leaving only the vertical stroke behind
   (reads as a plain bar, not a bracket). The right-edge bleed is safe at
   a larger offset since the path's real content stops at x=23 of 34;
   the bleed there eats into the glyph's own empty margin, not its shape. */
.philosophy-mark {
  position: absolute;
  top: clamp(-1rem, -2vw, -0.25rem);
  right: clamp(-3rem, -6vw, -1rem);
  width: clamp(12rem, 26vw, 20rem);
  height: clamp(12rem, 26vw, 20rem);
  color: var(--mauve-deep);
  opacity: 0.16;
  pointer-events: none;
}
.philosophy-mark svg { width: 100%; height: 100%; }

.philosophy-inner {
  position: relative;
  z-index: 1;
  max-width: var(--container);
  margin: 0 auto;
  padding: clamp(4.5rem, 10vw, 8rem) clamp(1.25rem, 4vw, 2.5rem);
}

.philosophy h2 {
  color: var(--plum-deep);
  max-width: 18ch;
  margin-bottom: clamp(3rem, 8vw, 5rem);
}

/* The heading runs the section's full width as one big typographic
   statement; the lead line and the supporting copy then split into a
   two-column deck beneath it so the reading text actually fills that
   width too, instead of hugging the left edge of a wide, empty field. */
.philosophy-deck {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
  padding-top: clamp(1.5rem, 4vw, 2.5rem);
  border-top: 1px solid var(--line);
}

.philosophy-lead {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
  line-height: 1.12;
  letter-spacing: -0.01em;
  color: var(--plum-deep);
  max-width: 16ch;
}

.philosophy-text { display: flex; flex-direction: column; gap: 1.25rem; }
.philosophy-text p { color: var(--ink); font-size: 1.1rem; max-width: 40ch; }

/* ==========================================================================
   Services
   ========================================================================== */

.services { background: var(--cream); }

.services-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: clamp(4.5rem, 10vw, 8rem) clamp(1.25rem, 4vw, 2.5rem);
}

.services h2 { max-width: none; margin-bottom: clamp(3rem, 8vw, 5rem); }

/* Heading and list both run the section's full width now (no more
   heading-alone-in-a-column with empty space below it); each row is its
   own grid so index / name / description actually use that width
   instead of huddling on the left with the description flipped
   right-aligned into the gap. */
.service-list { border-top: 1px solid var(--line); }

.service-row {
  position: relative;
  display: grid;
  grid-template-columns: 3rem minmax(10rem, 16rem) 1fr;
  align-items: baseline;
  gap: clamp(1rem, 3vw, 2rem);
  padding: clamp(1.4rem, 3vw, 2rem) 0.5rem;
  transition: background-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.service-row:hover {
  background-color: var(--cream-deep);
  transform: translateX(0.6rem);
}

/* The divider itself draws in left-to-right the first time each row
   scrolls into view, riding the same [data-reveal]/.is-visible toggle
   as everything else rather than a bespoke animation. */
.service-row::after {
  content: "";
  position: absolute;
  left: 0.5rem;
  right: 0.5rem;
  bottom: 0;
  height: 1px;
  background: var(--line);
  transform: scaleX(1);
  transform-origin: left;
}
html.js-reveal .service-row::after {
  transform: scaleX(0);
  transition: transform 900ms var(--ease-out);
}
html.js-reveal .service-row.is-visible::after { transform: scaleX(1); }

.service-index {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--mauve-deep);
  font-variant-numeric: tabular-nums;
}
.service-name { font-weight: 600; font-size: clamp(1.1rem, 1.6vw, 1.35rem); }
.service-desc { color: var(--ink-soft); text-align: left; max-width: 42ch; }

.service-categories {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 3vw, 2rem);
}

.service-category {
  position: relative;
  min-height: clamp(15rem, 28vw, 22rem);
  padding: clamp(2rem, 5vw, 3.5rem);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  border-radius: 0 var(--radius-lg) var(--radius-lg) var(--radius-lg);
  transition: transform var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}
.service-category--damen { background: var(--mauve); color: var(--plum-deep); }
.service-category--herren { background: var(--sage); color: var(--sage-deep); }
@media (hover: hover) and (pointer: fine) {
  .service-category:hover { transform: translateY(-0.35rem); }
}
.service-category-title {
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 5vw, 4.6rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  margin-left: 1rem;
}
.service-category-link {
  margin-top: 1.25rem;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1.25rem;
  border-top: 1px solid currentColor;
  font-weight: 600;
}
.service-category-corner {
  position: absolute;
  top: 1.5rem;
  left: 1.5rem;
  width: 4rem;
  height: 4rem;
  border-top: 0.6rem solid currentColor;
  border-left: 0.6rem solid currentColor;
  opacity: 0.22;
}

@media (min-width: 861px) {
  .service-category {
    min-height: clamp(12rem, 19vw, 16rem);
    padding: clamp(1.75rem, 3vw, 2.5rem);
  }
}

/* ========================================================================== 
   Price-list pages
   ========================================================================== */

.price-page { background: var(--cream); }
.price-hero {
  position: relative;
  overflow: hidden;
  background: var(--mauve);
}
.price-hero--herren { background: var(--sage); }
.price-hero-inner,
.price-content {
  width: min(100%, var(--container));
  margin: 0 auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}
.price-hero-inner { padding-block: clamp(4rem, 10vw, 7rem); }
.price-back {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
  font-weight: 600;
}
.price-hero h1 {
  color: var(--plum-deep);
  font-size: clamp(3.5rem, 9vw, 7rem);
  max-width: none;
}
.price-hero--herren h1 { color: var(--sage-deep); }
.price-intro { margin-top: 1rem; color: var(--ink-soft); font-size: 1.1rem; }
.price-content { padding-block: clamp(3.5rem, 8vw, 6rem); }
.price-group + .price-group { margin-top: clamp(3rem, 7vw, 5rem); }
.price-group h2 {
  color: var(--plum-deep);
  font-size: clamp(1.9rem, 3vw, 2.5rem);
  margin-bottom: 1.25rem;
}
.price-list { border-top: 1px solid var(--line); }
.price-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 1.5rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--line);
}
.price-row dt { color: var(--ink); }
.price-row dd {
  margin: 0;
  color: var(--plum-deep);
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.price-note { margin-top: 2rem; color: var(--ink-soft); font-size: 0.9rem; }
.price-contact {
  margin-top: clamp(3rem, 7vw, 5rem);
  padding: clamp(2rem, 5vw, 3rem);
  background: var(--sage);
  border-radius: 0 var(--radius-md) var(--radius-md) var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}
.price-contact h2 { color: var(--sage-deep); font-size: clamp(1.9rem, 3vw, 2.5rem); }

/* ==========================================================================
   Gallery
   ========================================================================== */

.gallery { background: var(--sage); }

.gallery-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: clamp(4.5rem, 10vw, 8rem) clamp(1.25rem, 4vw, 2.5rem);
}

.gallery h2 { color: var(--sage-deep); margin-bottom: clamp(2.5rem, 6vw, 4rem); }

.gallery-grid {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
}

.gallery-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.25rem, 3vw, 2rem);
}

.gallery-item {
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius-sm);
  height: 100%;
  transition: transform var(--dur-base) var(--ease-out);
}
.gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1);
  transition: transform var(--dur-base) var(--ease-out);
}
html.js-reveal .gallery-item img { transform: scale(1.08); }
html.js-reveal .gallery-item.is-visible img { transform: scale(1); }
@media (hover: hover) and (pointer: fine) {
  .gallery-item:hover img { transform: scale(1.045); }
}

.gallery-item--wide { aspect-ratio: 16 / 8.6; }
.gallery-row .gallery-item { aspect-ratio: 4 / 3; }

.gallery-item--tilt { transform: rotate(-1.4deg); }
@media (hover: hover) and (pointer: fine) {
  .gallery-item--tilt:hover { transform: rotate(0deg); }
}

/* ==========================================================================
   Location / contact
   ========================================================================== */

.location { background: var(--cream); }

.location-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: clamp(4.5rem, 10vw, 8rem) clamp(1.25rem, 4vw, 2.5rem);
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(22rem, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: stretch;
}

.location-inner > *,
.location-info > * { min-width: 0; }

/* Stretch, not center: the form column (four fields plus a button) is
   reliably taller than the photo+address column. Centering the shorter
   column inside that extra height just splits the dead space evenly
   above and below it; stretching both children instead lets the photo
   grow to fill the row (object-fit: cover handles the crop) and lets
   the details column center ITS content within its own full height, so
   neither side reads as floating in unused space. */
.location-info {
  display: grid;
  grid-template-columns: minmax(12rem, 0.8fr) minmax(17rem, 1fr);
  gap: clamp(1.5rem, 2.5vw, 2.5rem);
  align-items: stretch;
}
.location-photo {
  border-radius: var(--radius-sm);
  width: 100%;
  height: 100%;
  object-fit: cover;
  max-height: 44rem;
  transition: transform var(--dur-slow) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .location-photo:hover { transform: scale(1.02); }
}

.location-details { display: flex; flex-direction: column; justify-content: center; }
.location-details h2 {
  color: var(--plum-deep);
  font-size: clamp(2.25rem, 2.8vw, 3rem);
  line-height: 1.02;
  margin-bottom: 1.5rem;
}

.location-details address {
  font-size: 1rem;
  line-height: 1.7;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1.25rem;
}

.hours div { display: flex; justify-content: space-between; gap: 1rem; padding: 0.4rem 0; }
.hours dt { color: var(--ink-soft); }
.hours dd { margin: 0; font-variant-numeric: tabular-nums; }

.hours-note {
  margin-top: 0.85rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  font-style: italic;
  max-width: none;
}

.location-cta {
  background: var(--sage);
  border-radius: var(--radius-md);
  padding: clamp(2rem, 4vw, 2.75rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.location-cta h2 { color: var(--sage-deep); font-size: clamp(1.9rem, 3vw, 2.5rem); }
.cta-intro { color: var(--ink-soft); margin-top: 0.75rem; margin-bottom: 1.75rem; }
.location-cta .btn svg { width: 1.2rem; height: 1.2rem; }

/* ==========================================================================
   Footer
   ========================================================================== */

.footer { background: var(--plum); color: var(--on-plum); }

.footer-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: clamp(3rem, 6vw, 4.5rem) clamp(1.25rem, 4vw, 2.5rem);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 2rem;
}

/* on the plum footer background, the mark's default plum fill would
   vanish; it swaps to the wood accent there, same as the old mark did. */
.footer-logo .brandmark { height: 1.9rem; }
.footer-logo .brandmark-mark { fill: var(--wood); }

.footer-links { display: flex; gap: 1.75rem; font-size: 0.95rem; justify-self: center; }
.footer-links a { opacity: 0.85; transition: opacity var(--dur-fast) var(--ease-out); }
.footer-links a:hover { opacity: 1; }
.footer-links .footer-instagram {
  width: 44px;
  height: 44px;
  margin-block: -0.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.footer-instagram svg {
  width: 1.4rem;
  height: 1.4rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
}

.footer-meta { text-align: right; font-size: 0.9rem; opacity: 0.75; line-height: 1.6; }
.footer-meta p { margin-top: 0.15rem; }

.footer-legal {
  max-width: var(--container);
  margin: 0 auto;
  padding: 1.25rem clamp(1.25rem, 4vw, 2.5rem) clamp(1.75rem, 3vw, 2.25rem);
  border-top: 1px solid rgba(248, 244, 239, 0.16);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.85rem;
  opacity: 0.75;
}
.footer-legal nav { display: flex; gap: 1.25rem; }
.footer-legal a { opacity: 0.85; transition: opacity var(--dur-fast) var(--ease-out); }
.footer-legal a:hover { opacity: 1; }

/* ==========================================================================
   Legal pages (Impressum, Datenschutz)
   ========================================================================== */

.legal { background: var(--cream); }
.legal-inner {
  max-width: 46rem;
  margin: 0 auto;
  padding: clamp(3rem, 8vw, 5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(4rem, 10vw, 6rem);
}
.legal-inner h1 {
  font-size: clamp(2rem, 8vw, 3.25rem);
  /* "Datenschutzerklärung" and other long German compound legal terms are
     single unbreakable words that can be wider than a narrow phone
     screen at this font size; hyphens:auto (with lang="de" on <html>)
     wraps them at proper syllable boundaries instead of overflowing the
     viewport, with break-word as a fallback for browsers without a
     German hyphenation dictionary. */
  overflow-wrap: break-word;
  -webkit-hyphens: auto;
  hyphens: auto;
}
.legal-updated { color: var(--ink-soft); margin-top: 0.5rem; margin-bottom: 2.5rem; }
.legal-inner h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.3rem, 2.2vw, 1.6rem);
  color: var(--plum-deep);
  margin-top: 2.5rem;
  margin-bottom: 0.85rem;
}
.legal-inner h2:first-of-type { margin-top: 0; }
.legal-inner p { margin-bottom: 1rem; max-width: 68ch; }
.legal-inner ul { margin: 0 0 1.25rem 0; padding-left: 1.25rem; list-style: disc; max-width: 68ch; }
.legal-inner li { margin-bottom: 0.4rem; }
.legal-inner a { color: var(--plum); text-decoration: underline; text-underline-offset: 0.15em; }
.legal-inner a:hover { color: var(--plum-deep); }

/* ========================================================================== 
   Not found
   ========================================================================== */

.not-found {
  min-height: calc(100svh - var(--nav-h));
  display: grid;
  place-items: center;
  background: var(--sage);
}
.not-found-inner {
  width: min(100%, 46rem);
  padding: clamp(4rem, 12vw, 8rem) clamp(1.25rem, 4vw, 2.5rem);
}
.not-found-code {
  color: var(--mauve-deep);
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 1rem;
}
.not-found h1 { max-width: 12ch; }
.not-found p {
  max-width: 42ch;
  margin-top: 1.5rem;
  color: var(--sage-deep);
}
.not-found .btn { margin-top: 2rem; }

/* ==========================================================================
   Scroll reveal
   ========================================================================== */

/* Safe by default: visible, no motion, no dependency on JS. The
   html.js-reveal class (set by a synchronous inline script in <head>,
   see index.html) is the only thing that opts an element back into the
   hide-then-reveal choreography, so a page where JS never runs at all
   never hides anything in the first place. */
[data-reveal] { opacity: 1; transform: none; }

html.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
html.js-reveal [data-reveal].is-visible { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  html.js-reveal [data-reveal] { opacity: 1; transform: none; transition: none; }
  .gallery-item img { transition: none; }
  * { animation-duration: 0.001ms !important; }
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1024px) {
  .philosophy-deck { grid-template-columns: 1fr; gap: clamp(1.5rem, 4vw, 2.5rem); }
  .location-inner { grid-template-columns: 1fr; }
  .location-info { grid-template-columns: minmax(12rem, 0.75fr) minmax(17rem, 1fr); }
  .location-photo { max-height: 32rem; }
}

@media (max-width: 860px) {
  .nav-links, .nav-cta { display: none; }
  .nav-toggle { display: flex; }

  .nav-inner {
    width: 100%;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.25rem;
    padding-inline: 1rem 0.5rem;
  }
  .nav-actions {
    justify-self: end;
    gap: 0.25rem;
  }

  /* The brandmark SVG is a fixed-aspect wordmark, not text that reflows:
     at its nav-bar height (1.6rem) it renders ~247px wide, which plus the
     theme toggle, the hamburger, their gaps, and nav padding overflows
     almost every phone viewport (needs ~399px, most phones are 360-412px).
     Shrinking it here is the fix, not squeezing the surrounding gaps. */
  .logo .brandmark { height: 1.2rem; }
  .footer-logo .brandmark { height: 1.6rem; }

  /* Desktop bottom-anchors the hero copy on purpose (full-bleed photo,
     text sitting low over it). On a mobile-height hero that same anchor
     pushes the text uncomfortably close to the bottom edge instead, so
     mobile centers it vertically in the available space instead. */
  .hero { min-height: 34rem; align-items: center; }
  .hero-bg { object-position: 32% 40%; }
  .hero-scrim {
    background:
      linear-gradient(0deg, rgba(55, 23, 74, 0.88) 0%, rgba(55, 23, 74, 0.5) 45%, rgba(55, 23, 74, 0.12) 75%);
  }
  .hero-inner { padding-top: 2.5rem; padding-bottom: 2.5rem; }
  .hero-content { width: calc(100% - 1.25rem); max-width: none; margin-left: 1.25rem; }
  .hero-sub { width: 100%; max-width: 28ch; }
  .hero-corner {
    top: -1.9rem;
    left: -1.75rem;
    width: 5rem;
    height: 5rem;
  }
  .hero-content .btn { margin-top: 1.75rem; }

  .location-inner { grid-template-columns: 1fr; }

  .gallery-item--wide { aspect-ratio: 4 / 3; }
  .gallery-item--tilt { transform: rotate(-1deg); }

  .footer-inner {
    grid-template-columns: 1fr;
    text-align: left;
    gap: 1.5rem;
  }
  .footer-links { justify-self: start; flex-wrap: wrap; }
  .footer-meta { text-align: left; }
  .service-categories { grid-template-columns: 1fr; }
  .price-contact { align-items: flex-start; flex-direction: column; }
}

@media (max-width: 520px) {
  .service-row { grid-template-columns: 1fr; gap: 0.35rem; }
  .service-index { order: -1; }
  .service-desc { text-align: left; }
  .gallery-row { grid-template-columns: 1fr; }
  .gallery-row .gallery-item { aspect-ratio: 16 / 11; }
  .hours div {
    display: grid;
    grid-template-columns: 5.5rem minmax(0, 1fr);
    justify-content: start;
    gap: 0.75rem;
  }
  .hours dd { text-align: left; }
  .location-info { grid-template-columns: 1fr; }
  .location-photo { max-height: 22rem; }
  .location-cta { width: 100%; }
  .service-category { min-height: 13rem; }
  .price-row { gap: 1rem; padding-block: 0.9rem; }
  .price-row dt { max-width: 19ch; }
}

@media (max-width: 360px) {
  .nav-inner {
    display: flex;
    justify-content: space-between;
    gap: 0.5rem;
    padding-inline: 1rem 0.5rem;
  }
  .logo .brandmark { height: 0.9rem; }
  .nav-actions { margin-left: auto; }
  .nav-actions { gap: 0.5rem; }
  .location-details h2 { font-size: 1.9rem; }
}
