/* assets/css/styles.css */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
img, picture, video { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; }

/* Respect reduced-motion preference: jump instantly instead of animating
   between in-page anchors (nav links, "back to top", etc.). */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

@font-face {
  font-family: 'Goudy Sans';
  src: url('../fonts/goudy-sans-medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-variable.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-variable.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-variable.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-variable.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --color-brand: #00a2b5;
  --color-ink: #231f20;
  --color-grey: #bdbcbc;
  --color-bg-light: #f5f5f5;
  --color-bg-dark: #4f4d49;
  --color-paper: #ffffff;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --container-width: 80rem;
  --content-width: 45rem;
  /* Figma's mobile frame: the header/nav bar uses 24px horizontal padding,
     while section content (.content) uses a wider, separate 48px — two
     different values, not one shared mobile gutter. */
  --gutter-mobile: 1.5rem;
  --gutter-mobile-content: 3rem;
  --gutter-desktop: 5rem;
  --font-heading: 'Goudy Sans', -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Inter', -apple-system, 'Segoe UI', sans-serif;
}

body {
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--color-ink);
  background: var(--color-paper);
  line-height: 1.5;
  font-size: 16px;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 500;
  line-height: 1.2;
  color: var(--color-ink);
}
/* Figma: the hero H1 is 32px on the mobile frame, 40px on desktop — a
   real breakpoint-specific size, not a rounding artifact of resizing. */
h1 { font-size: 2rem; }
h2 { font-size: 2rem; }
h3 { font-size: 1.5rem; line-height: 1.5; }
h4 { font-size: 1.25rem; line-height: 1.3; }

/* Every text link (regardless of its base ink/white color) underlines and
   turns brand-mint on hover/focus — a deliberate, explicit site-wide policy
   (overrides a couple of spots where Figma itself showed a link without an
   underline, e.g. the footer mailto address). The primary site nav is
   navigational UI, not a prose link, and keeps its own distinct treatment
   (no underline, mint only for the current/hovered section). */
a { color: var(--color-ink); text-decoration: underline; }
a:hover, a:focus-visible { color: var(--color-brand); }
a:focus-visible, button:focus-visible { outline: 3px solid var(--color-brand); outline-offset: 2px; }

.container {
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
  padding-inline: var(--gutter-mobile);
}

.content {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
  padding-inline: var(--gutter-mobile-content);
}

/* Re-verified live via the Desktop Bridge across every instance of this
   role (hero/Kontakt "Sie erreichen...", Praxisteam/Einblicke/Buch
   taglines, Fachartikel's "PDF per E-Mail" label, Leistungen's intro
   label): 14px on mobile, 16px at desktop, consistently — not a flat 16px
   with a couple of scoped mobile exceptions as this had been built. */
.uppercase-label {
  font-weight: 600;
  text-transform: uppercase;
  color: var(--color-brand);
  font-size: 0.875rem;
}

/* Standard clip-based visually-hidden pattern: keeps content in the
   accessibility tree and document outline for screen-reader users while
   removing it from visual layout. Used for section-level headings that
   have no visible on-page title (#fachartikel, #zitat). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (min-width: 64rem) {
  .container { padding-inline: var(--gutter-desktop); }
  .content { padding-inline: 0; }
  h1 { font-size: 2.5rem; }
}

/* .site-header is the full-viewport-width sticky bar (background only);
   .site-header__inner is the 80rem-capped, centered content row inside it
   — this split is what keeps the header's background spanning edge to
   edge at any viewport width while the logo/nav stay aligned with the
   rest of the page's content at wide viewports. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  width: 100%;
  background: var(--color-paper);
  /* Not in the static Figma frame (which never shows a scrolled state),
     but explicitly requested: separates the sticky header from whatever
     content sits under it once the page scrolls — same drop-shadow value
     used sitewide ("PMB Drop Shadow v01"). */
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
}

.site-header__inner {
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Figma mobile: pt-24 pb-16 px-24 — asymmetric, not one uniform value. */
  padding: 1.5rem 1.5rem 1rem;
}

.site-header__logo img { height: 3.4167rem; width: 7.5rem; }

/* Figma's mobile nav trigger is the literal word "Menü", right-aligned,
   in the heading font — not an icon. aria-expanded/aria-label still track
   open/closed state for assistive tech; the visible label stays static
   ("Menü") since Figma shows no separate "closed" visual for this button. */
.nav-toggle {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-heading);
  font-size: 1.125rem;
  line-height: 1.25;
  color: var(--color-ink);
  -webkit-tap-highlight-color: transparent;
}
/* Figma's overlay-open frame shows the "Menü" label itself turn mint while
   its panel is expanded — matching the mint "active state" convention
   used for the current nav item everywhere else in this design. */
.nav-toggle[aria-expanded="true"] { color: var(--color-brand); }

/* Figma: the mobile menu is a floating overlay panel (its own white card
   with a drop-shadow) anchored under the header bar, not an in-flow
   accordion that pushes the page content down — positioned against
   .site-header (the nearest positioned ancestor, sticky) so it spans the
   full viewport width regardless of .site-header__inner's own
   content-width cap. */
.site-nav {
  display: none;
  position: absolute;
  /* 100% + sub-pixel rounding on the header's own fractional height
     (94.667px on mobile) can leave a hairline gap showing whatever sits
     behind the header. Overlap by 1px to guarantee a seamless edge. */
  top: calc(100% - 1px);
  left: 0;
  right: 0;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-6) var(--space-6);
  background: var(--color-paper);
  /* "PMB Drop Shadow v01" — verified as a real 16px blur radius by reading
     the effect directly off the live Figma nodes via the Desktop Bridge
     (figma.getNodeByIdAsync(...).effects), same value used on every card
     sitewide. An earlier pass had used 8px, trusting the REST API's
     Tailwind-converted `get_design_context` output, which mistranslated
     this specific value — the Plugin API's raw effect.radius is ground
     truth. */
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
  /* A 16px-blur shadow spreads past the panel's own top edge, bleeding
     visibly into the header above it. Clip flush at the top (0) while
     leaving room below/sides for the shadow to render in full. */
  clip-path: inset(0 0 -100px 0);
}
.site-nav.is-open { display: flex; }
.site-nav a {
  display: block;
  width: 100%;
  text-align: center;
  color: var(--color-ink);
  text-decoration: none;
  font-family: var(--font-heading);
  font-size: 1.5rem;
  line-height: 1.5;
}
.site-nav a:hover, .site-nav a.is-current { color: var(--color-brand); }
/* "Praxisteam"/"Unser Buch" are the full labels on mobile; desktop shows
   the shortened "Team"/"Buch" instead (per direct request, mobile unchanged) —
   both spans exist in the markup and CSS toggles which one is shown. */
.nav-label--short { display: none; }
.site-nav__close {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Stacks on top of the panel's own 12px gap for a full 36px gap above
     the close icon, per Figma. */
  margin-top: var(--space-5);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

@media (min-width: 64rem) {
  .site-header__inner {
    display: flex;
    align-items: flex-start;
    gap: 3rem;
    padding-block: 2.25rem 1.5rem;
    /* Symmetric 80px both sides — re-verified fresh via the Desktop Bridge.
       An earlier pass found this asymmetric (24px left / 80px right) and
       documented it as such; the user has since made it symmetric in
       Figma, matching the standard desktop gutter on both sides. */
    padding-inline: var(--gutter-desktop);
  }
  .site-header__bar,
  .site-nav {
    width: auto;
    padding-inline: 0;
  }
  .site-header__bar {
    padding-block: 0;
    flex-shrink: 0;
  }
  .site-header__logo img { height: 5.125rem; width: 11.25rem; }
  .nav-toggle, .site-nav__close { display: none; }
  .site-nav {
    display: flex;
    position: static;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    flex: 1 1 0;
    gap: 2.5rem;
    padding: 0;
    background: none;
    box-shadow: none;
    /* Figma's nav-links group has its own 16px top offset within the
       header row (align-items: flex-start); measured against the live
       logo, that reads 2px too low — nudged up to 14px. */
    padding-block: 0.875rem 0;
  }
  .site-nav a { width: auto; text-align: left; padding: 0; font-size: 1.125rem; line-height: 1.25; }
  .nav-label--full { display: none; }
  .nav-label--short { display: inline; }
}

.hero { position: relative; }
.hero__media { position: relative; aspect-ratio: 16 / 9; background: var(--color-ink); overflow: hidden; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; opacity: 0.75; }
.hero__media button {
  position: absolute; inset: 0; margin: auto; width: 4rem; height: 4rem;
  background: none; border: none; cursor: pointer; padding: 0;
}
.hero__video-frame { width: 100%; aspect-ratio: 16 / 9; border: 0; }
.hero {
  position: relative;
}
.hero__content {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-block: var(--space-7);
}
.hero__welcome h1 { color: var(--color-brand); }
.hero__welcome p { margin-top: var(--space-3); }
/* Figma fuses the H1 into the same text node as the paragraphs beneath it,
   with an explicit per-paragraph spacing value on the H1's own line — 20px
   mobile, 24px desktop (getRangeParagraphSpacing on just the H1's line;
   see the Leistungen comment further down for why the node's overall
   .paragraphSpacing can't be read directly — it's figma.mixed here too,
   since the body paragraphs below it use var(--space-3) instead). This
   overrides the var(--space-3) that .hero__welcome p above would otherwise
   put here, same as every other paragraph pair. */
.hero__welcome h1 + p { margin-top: 1.25rem; }
.hero__signature { font-weight: 600; }
/* Figma groups the hero's contact column into 3 sub-blocks (Kontakt info,
   Telefonzeiten, Öffnungszeiten) 36px apart — each with its own tighter
   16px-per-line internal spacing, not one flat list of children all
   spaced alike. The "Kontakt" heading's own line uses that same 16px
   value for its paragraph spacing too (verified live), so no override is
   needed for it specifically — the general rule above already matches. */
.hero__contact { display: flex; flex-direction: column; gap: 2.25rem; }
.hero__contact-block > * + * { margin-top: 1rem; }
/* Same fused-node situation for "Telefonzeiten"/"Öffnungszeiten": each
   heading's own paragraph-spacing value (verified live) is 8px, not the
   16px a previous pass assumed. */
.hero__hours h3 { margin-bottom: var(--space-2); }
/* Figma: only the hour-detail paragraphs (the 4 plain, class-less <p>s
   under Telefonzeiten/Öffnungszeiten) in the hero's compact contact column
   are explicitly 14px — .hero__phone and .uppercase-label are their own,
   separately-specified 16px roles and must stay excluded. The Kontakt
   section's own (larger, later) copy of the hour paragraphs is a separate,
   explicitly-16px treatment; the two are not meant to match. */
.hero__hours p { font-size: 0.875rem; }
/* Figma: the day-abbreviation ("Mo, Di, Do" / "Mi" / "Fr") is semibold,
   the time range next to it is regular — shared by the hero's compact
   copy of the hours and the Kontakt section's own larger copy. */
.hours__day { font-weight: 600; }
/* Figma has the two blocks disagree on their own internal gap — 12px
   between Telefonzeiten's two lines, 8px between Öffnungszeiten's —
   flagged as a likely inconsistency, but implemented exactly as specced. */
.hero__hours--telefonzeiten p + p { margin-top: var(--space-3); }
.hero__hours--oeffnungszeiten p + p { margin-top: var(--space-2); }
/* Figma's Willkommen "Content" wrapper sets a mint (--color-brand) base
   text color inherited by every child that has no more specific color
   class — the H1, the "Kontakt" heading, the "Sie erreichen uns..." label,
   and the Telefonzeiten/Öffnungszeiten headings all inherit it (verified
   against the get_design_context capture); only the address link, phone
   number, and hour-detail paragraphs have an explicit ink override. This
   codebase doesn't replicate Figma's wrapper-inheritance mechanism, so
   each of those inheriting elements needs its own explicit color rule. */
/* 24px on mobile, 32px (the sitewide h2 default) at desktop — was
   inheriting the 32px default unconditionally. */
.hero__contact h2 { color: var(--color-brand); font-size: 1.5rem; }
.hero__hours h3 { color: var(--color-brand); font-size: 1.25rem; line-height: 1.3; }
.hero__address { display: block; font-weight: 600; text-decoration: underline; }
/* "Sie erreichen uns am besten über die Online-Rezeption." — only the
   product-name span is underlined in Figma, not the whole sentence. Now a
   <button> (diagnostic id for the 321med vendor script, see the HTML
   comments), so it needs its native chrome stripped back to plain
   inline text — no border/background/cursor-default, inherit font. */
.hero__rezeption-link {
  display: inline;
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: underline;
}
.hero__rezeption-link:hover, .hero__rezeption-link:focus-visible { color: var(--color-ink); }

@media (min-width: 64rem) {
  .hero__content { flex-direction: row; gap: 5rem; padding-block: var(--space-8); }
  .hero__welcome { flex: 1 1 0; max-width: 24rem; }
  .hero__contact { flex: 0 0 16rem; }
}

.button {
  display: inline-block; width: fit-content; padding: var(--space-3) var(--space-6);
  border-radius: 999px; text-decoration: none; font-weight: 700;
}
.button--primary { background: var(--color-brand); color: #fff; }
.button--primary:hover { opacity: 0.9; }

/* Direct request: match Figma's literal floating-card positioning
   (including overlapping the header), not an in-flow bar. A previous pass
   ("Final-review Fix 1") deliberately moved this into normal document flow
   instead, because an absolute overlay covered the page's own <h1> whenever
   the CMS message got long — that failure mode is real and is being
   reintroduced knowingly here, flagged per the standing rule: on
   impressum.html/datenschutz.html (no tall hero under it) and on index.html
   at narrow widths, a long enough banner message WILL cover page content
   beneath it again.

   Positioned against .site-header (its nearest sticky/positioned ancestor,
   same mechanism as .site-nav above) at Figma's own canvas y — 75px mobile,
   106px desktop — both BEFORE the header's own bottom edge, i.e. genuinely
   overlapping it. z-index: -1 (scoped to .site-header's own stacking
   context, which position:sticky + z-index establish) paints the banner
   UNDER .site-header's own opaque background, matching Figma's layer order
   (Announcement Bar sits below Header in the layer list) — only the part
   of the card that extends past the header's own box (which has no
   background beyond its own height) stays visible, giving the "peeking out
   from under the header" look.

   FLAGGED FINDING: the dismiss (×) button sits inside the overlapped
   region at both breakpoints — Figma's own layout puts roughly the top
   half of that 24×24 icon behind the header (measured: ~12px of it on
   desktop, ~8px on mobile), which is genuinely unclickable there since
   the header's opaque background sits in front of it at those pixels.
   This is a real usability gap in the source design, not an
   implementation shortcut — flagging rather than silently moving the
   icon down to "fix" it. */
.banner {
  position: absolute;
  top: 4.6875rem; /* 75px */
  left: var(--gutter-mobile);
  right: var(--gutter-mobile);
  z-index: -1;
  background: var(--color-brand);
  border-radius: 0.5rem;
  /* Figma's "Layout Wrapper" inset around the text (see .banner__text
     below) used to carry its own top/left/bottom padding; direct request
     moved just the left component up here onto the card itself instead —
     .banner__text keeps only its flex/gap role now, no padding of its
     own, so it lines up with the dismiss icon at the top instead of
     sitting lower. Stacks with .banner__inner's own left padding below. */
  padding-left: 0.25rem;
  /* Figma specifies literal white text on this mint background — see the
     accessibility flag list for this pairing's contrast ratio. */
  color: #fff;
  /* Figma's one named drop-shadow style ("PMB Drop Shadow v01"), reused
     identically on every card in this design (accordion items,
     Schwerpunkte cards, the Buch card) — the banner overlay carries it too. */
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
}
@media (min-width: 64rem) {
  /* Figma: 720px wide (== --content-width exactly), right-aligned with
     the standard desktop gutter — not full-width, not centered. Direct
     request: aligned to the same right edge as the last nav link
     ("Kontakt"), not the raw viewport edge — .site-header itself spans
     the full viewport, but .site-header__inner (which the nav sits in)
     is centered and capped at --container-width, so past that width a
     plain `right: var(--gutter-desktop)` on .banner drifts away from the
     nav's actual right edge. This reproduces .site-header__inner's own
     centering math (half the leftover space beyond --container-width)
     so the two stay aligned at any viewport width. */
  .banner {
    top: 6.625rem; /* 106px */
    left: auto;
    right: calc(max(0rem, (100vw - var(--container-width)) / 2) + var(--gutter-desktop));
    max-width: var(--content-width);
    padding-left: 0.375rem;
  }
}
/* Figma's floating card uses 16px/20px top/bottom padding (16px left/right)
   and a 16px gap on mobile, 24px all around and a 24px gap at desktop —
   re-verified live. */
.banner__inner {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  padding: 1rem 1rem 1.25rem;
}
/* 16px both breakpoints — the user just unified this in Figma (desktop was
   18px before). Paragraph gap is 12px (getRangeParagraphSpacing on the
   live text node), not the 8px var(--space-2) an earlier pass used.
   Default weight is Medium — <strong> (from **bold** in banner.txt, see
   renderBannerHTML) is the only way any of it becomes Bold; there's no
   more automatic "first paragraph is bold" behavior. */
.banner__text { flex: 1 1 0; display: flex; flex-direction: column; gap: var(--space-3); font-size: 1rem; font-weight: 500; }
.banner__text strong { font-weight: 700; }
.banner__link { color: #fff; font-weight: 600; text-decoration: underline; width: fit-content; }
/* Exception to the site-wide "links turn mint on hover" policy: this link
   sits ON the brand-mint banner background, so a mint hover color would
   be effectively invisible against it (see flagged accessibility list).
   Keep it white on hover/focus instead — same as its resting state. */
.banner__link:hover, .banner__link:focus-visible { color: #fff; }
/* Figma's close icon (a real 24×24 "lucide/x" component, same one the nav
   uses — see renderBannerHTML) sits flush against the card's own padding,
   with no extra padding of its own around it — the icon itself stays put. */
.banner__dismiss {
  display: flex; background: none; border: none; padding: 0; cursor: pointer; flex-shrink: 0;
  position: relative;
}
/* Enlarges the actual clickable/tappable area to 44×44 (WCAG 2.5.8's
   minimum, and comfortable for a thumb) via an invisible pseudo-element
   that overflows past the 24×24 visible icon, rather than adding real
   padding that would push the icon away from Figma's exact position.
   Especially useful here since part of the visible icon already sits
   behind the header (see the .banner comment above on the overlap) —
   a bigger invisible target makes the remaining visible/unobscured
   sliver easier to actually hit. */
.banner__dismiss::before {
  content: '';
  position: absolute;
  inset: -0.625rem;
}
/* The global a/button focus-visible outline is --color-brand, which is
   invisible (1:1) against this banner's own brand-colored background.
   Override to ink here, which measures 5.31:1 against the brand background. */
.banner a:focus-visible, .banner button:focus-visible { outline-color: var(--color-ink); }

.section { padding-block: 3.75rem; }
.section--alt { background: var(--color-bg-light); }
.section--dark { background: var(--color-bg-dark); color: #fff; }
.section--dark h2, .section--dark h3, .section--dark h4 { color: #fff; }
.section--dark a { color: #fff; }
/* The site-wide a:hover rule and .section--dark a have equal specificity
   (one class + one tag each); without this, source order alone would let
   .section--dark a's white win over the hover state, silently defeating
   the "every link turns mint on hover" policy on dark section backgrounds. */
.section--dark a:hover, .section--dark a:focus-visible { color: var(--color-brand); }
/* Figma's Buch "Content" wrapper sets a mint (--color-brand) base color;
   the tagline paragraph has no more specific override so it inherits mint
   — same value as .uppercase-label's own default, so no override is
   needed here at all (this rule intentionally left removed, not just
   emptied) to let the base rule apply. See the accessibility flag list
   for this pairing's contrast ratio. */
/* The global a/button focus-visible outline (--color-brand) measures only
   2.82:1 on --color-bg-light and 2.74:1 on --color-bg-dark, both under the
   3:1 minimum for non-text UI contrast (SC 1.4.11), which would make the
   accordion's focus state hard to see once tabbed to. Override with
   already-passing tokens for each section background: ink on bg-light
   (14.95:1) and paper/white on bg-dark (8.43:1). */
.section--alt a:focus-visible, .section--alt button:focus-visible { outline-color: var(--color-ink); }
.section--dark a:focus-visible, .section--dark button:focus-visible { outline-color: var(--color-paper); }
.section h2 { margin-bottom: var(--space-4); }
.section p + p { margin-top: var(--space-4); }

/* This block's own desktop overrides were being immediately re-overridden
   by later, equal-specificity base rules further down the file (CSS
   cascade ties break on source order, not on which side is inside a
   media query) — every value below now lives at the very end of the
   file instead, guaranteed to come after every base rule it touches. */
@media (min-width: 64rem) {
  .section { padding-block: 5.625rem; }
}

/* Figma models "Leistungen" and "Schwerpunkte" as ONE combined section
   with a single 60px gap between the two content groups — not two
   separate sections each with their own .content gap (2.25rem/36px). */
.leistungen-schwerpunkte .content { display: flex; flex-direction: column; align-items: center; gap: 3.75rem; }
.leistungen-group, .schwerpunkte-group { display: flex; flex-direction: column; align-items: flex-start; width: 100%; }
/* Figma fuses "Leistungen" + its tagline + both lede paragraphs into ONE
   text node (verified live: paragraphSpacing is unset, so the only space
   between those lines is each line's own line-height) — .leistungen-group
   has 3 real DOM children (h2, .leistungen-intro, .accordion) though, and
   a flex `gap` applies between every child alike. Giving the group gap:0
   and moving the real 36px-mobile/32px-desktop gap onto .accordion's own
   margin-top (below) reproduces that: zero extra space below the
   heading/intro block, the real gap only before the accordion. */
.leistungen-group { gap: 0; }
.leistungen-group > .accordion { margin-top: 2.25rem; }
/* .schwerpunkte-group has only 2 real children (.schwerpunkte-intro,
   .schwerpunkte__layout) sharing this gap correctly already — Figma's
   "Schwerpunkte" frame itemSpacing is between exactly those two, so no
   restructuring needed here, only the same mobile/desktop split. */
.schwerpunkte-group { gap: 2.25rem; }
/* Leistungen/Schwerpunkte fuse their heading into the same Figma text node
   as the tagline/lede beneath it, with an explicit per-paragraph
   "paragraph spacing" value on the heading line — NOT zero (an earlier
   pass in this file misread this as unset because the node's overall
   .paragraphSpacing reads as figma.mixed, a Symbol that JSON.stringify
   silently drops; getRangeParagraphSpacing on just the heading's own line
   gives the real per-paragraph value: 20px mobile, 16px desktop). This
   replaces the sitewide ".section h2" 16px default (wrong at mobile) with
   the real measured value, and also overrides the flex `gap` further up
   this file for Leistungen specifically (h2 is a direct flex child there). */
.leistungen-group > h2, .schwerpunkte-intro > h2 { margin-bottom: 1.25rem; }
/* Figma: the lede paragraphs are 12px apart within their own intro block —
   not the section-wide 16px default, and not the group's own 32px/48px
   gap (which only separates heading/intro/content at the top level). */
.leistungen-intro p + p, .schwerpunkte-intro p + p { margin-top: var(--space-3); }

.accordion { display: flex; flex-direction: column; gap: var(--space-5); width: 100%; }
/* Figma's whole card (label row + body copy) shares ONE padding box, with
   a 24px gap between the label row and the body when it's showing. The
   panel animates open/closed via a CSS grid-rows trick (0fr → 1fr) rather
   than the old `hidden` attribute (display:none can't be transitioned);
   its own margin-top animates alongside so the 24px gap collapses away
   too, instead of leaving a stray gap above a zero-height panel. */
.accordion__item {
  background: var(--color-paper);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
  border-radius: 0.75rem;
  display: flex;
  flex-direction: column;
  padding: 1.25rem 1.75rem 1.25rem 2rem;
}
/* Open state gets its own padding (28px top / 32px bottom vs. the closed
   row's even 20px top/bottom) per Figma's two distinct component variants. */
.accordion__item.is-open { padding: 1.75rem 1.75rem 2rem 2rem; }
.accordion__trigger {
  /* flex-start, not center: direct request is that the chevron always
     sits at the top, in line with the label's first line, however many
     lines a longer label wraps to — align-items:center would instead
     center it against the whole wrapped block. For every label actually
     in this design (all one line), that's visually identical to centered
     alignment, which .accordion__chevron's own margin-top below
     reproduces precisely for the single-line case. */
  width: 100%; display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-5);
  padding: 0; background: none; border: none; cursor: pointer; text-align: left;
  /* Re-verified live against Figma (the user updated this style directly
     while this was being built): brand heading font, original case — no
     longer the small uppercase Inter label this used to be. Goudy Sans is
     only self-hosted at weight 500 (Medium), which is also the only
     weight Figma's own type style uses, so font-weight stays 500 rather
     than 600 to avoid a synthesized fake bold. Size is 20px on mobile,
     24px at desktop — a real breakpoint difference, not one shared size. */
  color: var(--color-brand); font-family: var(--font-heading); font-weight: 500; text-transform: none; font-size: 1.25rem; line-height: 1.5;
}
/* Nudges the 24px chevron down so its center lands on the first line's own
   center: (line-height − chevron height) / 2 = (30px − 24px) / 2 = 3px
   mobile, (36px − 24px) / 2 = 6px at the 24px desktop trigger size below. */
.accordion__chevron { flex-shrink: 0; margin-top: 0.1875rem; }
@media (min-width: 64rem) {
  .accordion__chevron { margin-top: 0.375rem; }
}
.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: 0;
  transition: grid-template-rows 0.22s ease, margin-top 0.22s ease;
}
/* 24px mobile — a real itemSpacing between two separate Figma text nodes
   (label, body) there. Desktop fuses them into ONE text node instead
   (verified live via getRangeParagraphSpacing on the fused node, across
   all 4 collapsibles): the real gap is 16px, not this same 24px — see the
   desktop override at the end of this file. */
.accordion__item.is-open .accordion__panel { grid-template-rows: 1fr; margin-top: var(--space-5); }
.accordion__panel-inner { overflow: hidden; min-height: 0; font-size: 0.875rem; }
.accordion__panel-inner p + p { margin-top: var(--space-2); }

/* Same 36px-mobile/48px-desktop split confirmed live for this wrapper and
   the two-card row inside it. */
.schwerpunkte__layout { display: flex; flex-direction: column; gap: 2.25rem; width: 100%; }
.schwerpunkte__row { display: grid; gap: 2.25rem; }
.schwerpunkte__card {
  background: var(--color-paper);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
  border-radius: 0.75rem;
  padding: var(--space-6);
  width: 100%;
}
/* Direct request, NOT yet reflected in Figma: Figma still shows these
   cards as plain, always-expanded text at every width (re-verified live —
   no accordion/chevron component here in either the mobile or desktop
   frame). Below the desktop breakpoint the heading + body reuse the exact
   same .accordion__trigger/.accordion__panel/.accordion__panel-inner
   classes and markup as the Leistungen accordion — same component, not a
   parallel look-alike — so they look and animate identically (including
   the trigger's own vertical-centering fix). Only .schwerpunkte__card's
   own background/shadow/padding stay its own (verified separately against
   Figma's card padding, which differs from the Leistungen accordion's).
   accordion.js's generic handler doesn't drive this one because desktop
   must stay non-collapsible, so a dedicated initSchwerpunkteCards() in
   accordion.js disables the trigger and forces the panel open there. */
.schwerpunkte__card.is-open .accordion__panel { grid-template-rows: 1fr; margin-top: var(--space-5); }
/* Disabled only at desktop (see initSchwerpunkteCards) — neutralize the
   browser's default disabled dimming/cursor so it still reads as the
   plain mint heading Figma shows there, not a greyed-out control. */
.schwerpunkte__card .accordion__trigger:disabled { opacity: 1; cursor: default; }
/* Figma: body text under Chronische Erkrankungen AND under Kinder/AVWS is
   explicitly 14px (Body text SM) throughout — not the site's 16px default.
   Only the section's own intro paragraphs (Schwerpunkte's own 2 lede
   paragraphs, outside the cards) stay 16px. */
.schwerpunkte__card p { font-size: 0.875rem; }
.schwerpunkte__card p + p { margin-top: var(--space-2); }

@media (min-width: 48rem) {
  .schwerpunkte__row { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 64rem) {
  /* Desktop: chevron hidden, panel always visually expanded (JS also
     forces panel.inert = false and disables the trigger — see
     initSchwerpunkteCards) — matches Figma's plain static card. */
  .schwerpunkte__card .accordion__chevron { display: none; }
  /* 16px, verified live against Figma's real per-paragraph spacing for
     this specific heading→body transition — not the 24px the reused
     .accordion__panel.is-open rule uses for the mobile-only collapsible
     state above (that value has no Figma equivalent to match, since this
     card isn't collapsible there at all). */
  .schwerpunkte__card .accordion__panel { grid-template-rows: 1fr; margin-top: var(--space-4); }
  .schwerpunkte__card .accordion__panel-inner { overflow: visible; }
}

/* .card/.card-grid: unused since Fachartikel switched to its own
   .fachartikel-buy__button (Task 6) — kept for potential reuse, fixed
   here (undefined --color-border was invalidating the whole border
   shorthand) rather than left broken-but-dormant. */
.card-grid { display: grid; gap: var(--space-5); margin-top: var(--space-6); }
.card { background: var(--color-paper); border: 1px solid var(--color-grey); border-radius: 0.75rem; padding: var(--space-5); }
.card h3 { font-size: 1.1rem; margin-bottom: var(--space-3); color: var(--color-brand); }

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

/* Figma: Praxisteam's Content gaps (h2→intro-label, intro-label→photo)
   are both 24px, not plain document-flow margins. .content itself is a
   plain block container (not flex) elsewhere on the site, so this needs
   its own explicit flex+gap rather than relying on a shared base rule. */
#team .content { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-5); }
#team .content > h2 { margin-bottom: 0; }
.team-photo img { width: 100%; height: auto; }
/* 12px on mobile, 14px at desktop. */
.team-photo figcaption { margin-top: var(--space-3); font-size: 0.75rem; color: var(--color-ink); }

/* --color-border doesn't exist (undefined custom property invalidates the
   whole `border` shorthand at computed-value time — these frames were
   rendering with NO border at all). Figma's mockup shows these as plain
   rounded-rectangle placeholders with no visible border in the provided
   frame, so removing the border entirely (rather than inventing a color)
   matches the source most literally. */
.embed-frame { aspect-ratio: 16 / 10; border-radius: 0.75rem; overflow: hidden; }
.embed-frame iframe { width: 100%; height: 100%; border: 0; }
/* 12px on mobile, 14px at desktop. */
.embed-frame__note { font-size: 0.75rem; color: var(--color-ink); text-align: right; }
/* Figma: heading/intro-copy block and image+caption block are each their
   own gap-32 (the section-wide .content default of 36px was too loose for
   this particular gap); the image→caption gap inside is a tighter,
   separate 12px. */
#einblicke .content { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-6); }
.einblicke-tour { display: flex; flex-direction: column; gap: var(--space-3); width: 100%; }
/* Figma fuses "Einblicke" + its tagline + lede into ONE text node with an
   explicit per-paragraph spacing value on the heading line — 20px mobile,
   16px desktop (getRangeParagraphSpacing on just the heading's line; the
   node's overall .paragraphSpacing reads as figma.mixed and silently
   vanishes under JSON.stringify, which is what led an earlier measurement
   on this same node astray twice — first to a flat 24px, then to 0). */
.einblicke-intro > h2 { margin-bottom: 1.25rem; }
.einblicke-intro > p + p { margin-top: 1rem; }

/* Figma: the whole Buch section is ONE white drop-shadow card (not a dark
   section with plain text) sitting on a colored page background — verified
   fresh via the Desktop Bridge (both the desktop and mobile "Unser Buch"
   frames), this is now brand mint (--color-brand), not the grey it used to
   be — the user changed it in Figma since this was last implemented. */
.buch-section { background: var(--color-brand); }
.buch-card {
  background: var(--color-paper);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
  border-radius: 0.75rem;
  display: flex;
  flex-direction: column;
  /* Figma: every direct child here (h2, tagline, the image+text row) is
     set to FILL/STRETCH, not centered-while-hugging-content — align-items
     defaults to stretch once this isn't overridden, which is what makes
     the heading/tagline/row actually span and left-align instead of
     shrink-wrapping to their own width and centering as a block. */
  gap: var(--space-5);
  padding: 1.75rem 2rem 2rem;
  width: 100%;
}
/* Same fix as .leistungen-group above: h2 is a direct flex child here, so
   the global ".section h2" margin-bottom would double up with this
   card's own gap. */
.buch-card > h2 { margin-bottom: 0; }
.buch-layout { display: grid; gap: var(--space-6); align-items: start; width: 100%; }
.buch-layout img { max-width: 15.3125rem; margin-inline: auto; }
/* Figma: the 4 body paragraphs, the Leseprobe link, and the price line are
   all explicitly 14px (Body text SM) — no larger/bolder emphasis on the
   price specifically, each 8px apart (not the section-wide 16px default). */
.buch-layout p { font-size: 0.875rem; }
.buch-layout p + p { margin-top: var(--space-2); }
/* Figma: the first body paragraph and the price line are semibold; the
   paragraphs between them are regular weight. */
.buch-layout p:first-child { font-weight: 600; }
.price { font-size: 0.875rem; font-weight: 600; }

@media (min-width: 48rem) {
  .buch-layout { grid-template-columns: 15.3125rem 1fr; }
  .buch-layout img { margin-inline: 0; }
}

.card-grid--2 { grid-template-columns: 1fr; }
.paypal-hosted-form { margin-top: var(--space-4); }
/* The single-option <select name="os0"> is required by the PayPal hosted
   button exactly as originally provided — Figma shows no dropdown here at
   all, so it's hidden visually rather than removed; a display:none form
   control still submits its selected value on submit. */
.paypal-hosted-form select { display: none; }
@media (min-width: 48rem) {
  .card-grid--2 { grid-template-columns: repeat(2, 1fr); }
}

/* Figma: the "Auszug aus dem Fachartikel..." lede and the body paragraphs/
   list items are all 14px (Body text SM) at both breakpoints. The
   "PDF per E-Mail..." label is also a <p class="uppercase-label"> and no
   longer needs its own override — .uppercase-label's base rule already
   does the same 14px-mobile/16px-desktop split this needs. Both ledes
   carry an extra .fachartikel-item__lede class purely so this 14px rule
   can target them specifically despite sharing .uppercase-label with the
   PDF label. */
.fachartikel-layout { display: flex; flex-direction: column; gap: var(--space-8); margin-top: var(--space-4); }
/* Figma fuses each article's title into the same text node as its lede
   paragraph, with an explicit per-paragraph spacing value on the title
   line — 20px mobile, 16px desktop (see the Leistungen comment above for
   why the node's own .paragraphSpacing can't just be read directly: it's
   figma.mixed here too). h2 carries the real value; the lede's own
   margin-top is zeroed so the two don't collapse into something bigger. */
.fachartikel-item > h2 { margin-bottom: 1.25rem; }
.fachartikel-item h2 + p { margin-top: 0; }
.fachartikel-item p, .fachartikel-item ul { margin-top: var(--space-3); font-size: 0.875rem; }
.fachartikel-item p.fachartikel-item__lede { font-size: 0.875rem; }
.fachartikel-item ul { padding-left: 1.25rem; }
.fachartikel-item li { margin-top: var(--space-2); font-weight: 600; }
/* Figma: the "Hilfe, ich bin ständig krank..." pull-quote paragraph is
   explicitly colored --color-bg-dark (#4f4d49) reused as a text color for
   visual de-emphasis against the white article background — every other
   paragraph in this section is plain --color-ink. */
.fachartikel-item__quote { color: var(--color-bg-dark); }
.fachartikel-buy { margin-top: var(--space-5); }
.fachartikel-buy__button {
  /* Figma specifies literal white text on the mint background — see the
     accessibility flag list for this pairing's contrast ratio. Mobile is
     centered with a shorter "Bestellen (PayPal)" label; desktop is
     right-aligned with the full "Kostenpflichtig bestellen (PayPal)". */
  width: 100%; background: var(--color-brand); color: #fff; border: none; border-radius: 0.5rem;
  padding: 1rem 1.25rem; font-family: var(--font-body); font-weight: 600; font-size: 1rem; text-align: center; cursor: pointer;
}
.fachartikel-buy__button:hover { opacity: 0.9; }
.fachartikel-buy__button-long { display: none; }

@media (min-width: 64rem) {
  /* Figma: full-width is a mobile-only treatment — the desktop button
     shrinks to its own content width instead of stretching the row. */
  .fachartikel-buy__button { width: auto; text-align: right; }
  .fachartikel-buy__button-short { display: none; }
  .fachartikel-buy__button-long { display: inline; }
}

@media (min-width: 64rem) {
  .fachartikel-layout { flex-direction: row; gap: var(--gutter-desktop); align-items: flex-start; }
  .fachartikel-item { flex: 1 1 0; }
}

#kontakt .content { display: flex; flex-direction: column; gap: 2.25rem; }
/* h2 is a direct flex child of .content here, so the global ".section h2"
   margin-bottom would double up with this gap. */
#kontakt .content > h2 { margin-bottom: 0; }
.kontakt-info-row { display: grid; gap: 2rem; }
/* Figma: address/phone/label are each 16px apart within the first block. */
.kontakt-info-block > * + * { margin-top: 1rem; }
.kontakt-hours h3 { margin-bottom: 1rem; }
/* Figma has the two blocks disagree on their own internal gap here too —
   12px under Telefonzeiten, 16px under Öffnungszeiten — implemented
   exactly as specced rather than normalized to one value. */
.kontakt-hours--telefonzeiten p + p { margin-top: var(--space-3); }
.kontakt-hours--oeffnungszeiten p + p { margin-top: 1rem; }
/* Figma: the Kontakt info-row's wrapper sets a mint base color; the
   address link and phone/hours paragraphs have explicit ink overrides,
   but the Telefonzeiten/Öffnungszeiten <h3> headings do not, so they
   inherit mint. */
.kontakt-info-row h3 { color: var(--color-brand); }
.kontakt-find { display: flex; flex-direction: column; gap: var(--space-6); width: 100%; }
/* Figma: "So finden Sie uns" is literal ink (#231f20), unlike the mint
   Kontakt/Telefonzeiten/Öffnungszeiten headings above it — was wrongly
   set to brand-mint. */
.kontakt-map-heading { color: var(--color-ink); }
/* No rounded corners on this embed — unlike .embed-frame's default
   (used elsewhere for the Einblicke 360°-tour embed), this one is meant
   square-cornered. */
/* Figma's mobile map is close to square (279×279, ~1:1) — much taller
   relative to its width than the wide 720:289 ratio used at desktop. */
.kontakt-map { aspect-ratio: 1 / 1; border-radius: 0; }
/* User-requested deviation from Figma's own static screenshot: a live,
   greyscale Google Maps embed pinned to the practice's address, replacing
   the placeholder that had mistakenly reused the Einblicke section's 360°
   indoor tour embed here. */
.kontakt-map iframe { filter: grayscale(1); }

.zitat { text-align: left; }
.zitat__quote { font-family: var(--font-heading); font-size: 2rem; line-height: 1.2; color: var(--color-grey); }
.zitat__attribution { margin-top: 1rem; font-family: var(--font-heading); font-size: 1.25rem; line-height: 1.3; color: var(--color-bg-light); }

@media (min-width: 48rem) {
  .kontakt-info-row { grid-template-columns: 1fr 11.25rem 11.25rem; }
}

.legal h1 { margin-bottom: var(--space-5); color: var(--color-brand); }
/* Impressum/Datenschutz have no dedicated Figma frame, so these sizes
   were never breakpoint-specific — h2/h3 sat at one fixed size at every
   viewport, which read as "stuck at the mobile size" on a wide screen.
   Scaled up at desktop below, following the same kind of mobile→desktop
   step used for every other heading role on the site (not a literal
   Figma value, since none exists for this page). */
.legal h2 { font-size: 1.25rem; margin-top: var(--space-7); margin-bottom: var(--space-3); color: var(--color-brand); }
.legal h3 { font-size: 1rem; margin-top: var(--space-5); margin-bottom: var(--space-2); color: var(--color-brand); }
.legal p { max-width: 42rem; }
.legal p + p { margin-top: var(--space-3); }

/* Clicking a main nav item (or landing on a URL with a hash) should leave
   the target section's top edge sitting flush against the sticky header's
   bottom edge — no gap, no overlap. scroll-margin-top is therefore set to
   the sticky header's own live-measured height exactly, not an
   approximation with slack: 94.667px below the 64rem breakpoint, 142px
   at/above it (the header's own padding/logo size both change there). */
/* "schwerpunkte" is a plain <div id> (Leistungen and Schwerpunkte share
   one <section>, per Figma), not a <section id> like the rest — included
   explicitly so a direct #schwerpunkte link still clears the header. */
section[id], #schwerpunkte { scroll-margin-top: 5.9167rem; }

@media (min-width: 64rem) {
  section[id], #schwerpunkte { scroll-margin-top: 8.875rem; }
}

.site-footer {
  background: var(--color-ink);
  color: var(--color-grey);
  padding-block: 3.75rem;
  text-align: center;
}
/* Figma itself only underlines the Impressum/Datenschutz link line and
   leaves the mailto link in the contact line unstyled (inherited grey,
   no underline). The user has since overridden that specific nuance with
   a site-wide policy: every text link underlines and turns mint on
   hover, no exceptions — so the contact mailto link is deliberately
   brought in line with that policy rather than left at its literal
   Figma treatment. */
.site-footer__links a { color: var(--color-bg-light); text-decoration: underline; }
.site-footer__links a:hover, .site-footer__links a:focus-visible { color: var(--color-brand); }
.site-footer__contact a { color: inherit; text-decoration: underline; }
.site-footer__contact a:hover, .site-footer__contact a:focus-visible { color: var(--color-brand); }
.site-footer__inner { display: flex; flex-direction: column; align-items: center; gap: 2.25rem; }
/* The middot separator was replaced with real spacing between the two
   links (double the ~14px gap the middot + its surrounding spaces used
   to produce), via flex gap instead of relying on collapsible whitespace
   between inline elements. */
.site-footer__links { display: inline-flex; gap: 1.75rem; font-family: var(--font-heading); font-size: 1.25rem; }
/* Figma: the contact line and the credit line beneath it are grouped
   together with their own tight 8px gap — not the outer 36px that
   separates them, as a group, from the Impressum/Datenschutz links line
   above. */
.site-footer__credit-block { display: flex; flex-direction: column; gap: var(--space-2); }
.site-footer__contact { font-size: 0.875rem; }
.site-footer__credit { font-size: 0.625rem; }

@media (min-width: 64rem) {
  .site-footer { padding-block: 5.625rem; }
}

/* Desktop overrides collected here deliberately, at the very end of the
   file: every one of these ties in specificity with its own mobile-first
   base rule declared earlier, and CSS breaks that tie by source order —
   not by which side is wrapped in a media query. Placing them earlier
   (as a previous pass did) meant a later, equal-specificity base rule
   could silently re-override the desktop value right back to the mobile
   one. Keeping all of them here guarantees they come last. */
@media (min-width: 64rem) {
  .uppercase-label { font-size: 1rem; }
  .leistungen-group > .accordion { margin-top: var(--space-6); }
  .leistungen-group > h2, .schwerpunkte-intro > h2 { margin-bottom: var(--space-4); }
  .schwerpunkte-group { gap: var(--space-7); }
  .schwerpunkte__layout { gap: var(--space-7); }
  .schwerpunkte__row { gap: var(--space-7); }
  .banner__inner { gap: var(--space-5); padding: var(--space-5); }
  .accordion__trigger { font-size: 1.5rem; }
  /* 16px, not the mobile 24px above — see the base-rule comment. */
  .accordion__item.is-open .accordion__panel { margin-top: var(--space-4); }
  .hero__contact h2 { font-size: 2rem; }
  .team-photo figcaption { font-size: 0.875rem; }
  .embed-frame__note { font-size: 0.875rem; }
  .legal h2 { font-size: 1.5rem; }
  .legal h3 { font-size: 1.125rem; }
  .kontakt-map { aspect-ratio: 720 / 289; }
  .einblicke-intro > h2 { margin-bottom: var(--space-4); }
  .fachartikel-item > h2 { margin-bottom: var(--space-4); }
  .hero__welcome h1 + p { margin-top: var(--space-5); }
}
