/* base/layers.css */
/* ==========================================================================
   Layer order. This file MUST load before every other stylesheet.
   Declaring the order up front means a host platform's CSS (WordPress core,
   a plugin, a builder) can never outrank ours by specificity accident.
   ========================================================================== */

@layer tokens, base, components, sections, utilities;


/* tokens/tokens.css */
/* ==========================================================================
   Design tokens. One flat semantic tier.
   Source: Figma 7MfxVZzdqWSEsWA6V8RGJd

   Values are taken from the Figma variables where variables exist, and from
   measured usage where the design uses raw values. Both are marked.
   Mapping back to Figma names: see CONVENTIONS.md section 4.
   ========================================================================== */

@layer tokens {
  :root {
    /* ---------------------------------------------------------------------
       Colour

       The signature brand colour is a GRADIENT, not a flat value. #4dd0ff and
       #9745ff appear 34 times each on Startseite and are the most-used colours
       in the design, yet neither is a Figma variable. The variable named
       "purple" (#9d72ce) is used exactly once on the whole page.
       Reported to the designer, reproduced as drawn.
       --------------------------------------------------------------------- */

    /* Surfaces */
    --color-surface: #ffffff;            /* figma: white */
    --color-surface-dark: #17203f;       /* figma: dark-navy */
    --color-surface-muted: #f2f2f2;      /* figma: light-gray */
    --color-surface-soft: #f6d3b1;       /* figma: peach. Used as the hero glow
                                            (see --gradient-hero), not as a flat fill. */

    /* Translucent surfaces. The card system is glassmorphic: white at low
       alpha over light backgrounds, navy at high alpha over imagery. */
    --color-glass-light: rgb(255 255 255 / 0.2);
    --color-glass-lighter: rgb(255 255 255 / 0.1);
    --color-glass-strong: rgb(255 255 255 / 0.9);
    --color-glass-dark: rgb(35 35 72 / 0.9);      /* #232348 at 90% */
    --color-glass-muted: rgb(242 242 242 / 0.2);

    /* Text */
    --color-text: #000000;               /* figma: black */
    --color-heading: #17203f;            /* figma: dark-navy, 21 uses */
    --color-heading-alt: #1b1d36;        /* raw, 7 uses. Near-duplicate of the
                                            above. Design inconsistency, kept
                                            so reproduction stays exact. */
    --color-on-dark: #ffffff;

    /* Accents */
    --color-accent: #9d72ce;             /* figma: purple. 1 use */
    --color-accent-deep: #323672;        /* figma: indigo. 4 uses */

    /* The real brand identity */
    --color-brand-from: #4dd0ff;         /* raw hex, 34 uses */
    --color-brand-to: #9745ff;           /* raw hex, 34 uses */
    --gradient-brand: linear-gradient(
      90deg,
      var(--color-brand-from),
      var(--color-brand-to)
    );

    /* Hero backdrop. Two layers, both measured off the full-resolution render
       because the SVG export of Rectangle 10 came back with its fill stripped.

       Layer 1, the warm glow: peach at 0.70 alpha, centred on the top-right
       corner, falling off linearly to zero by x≈240 and y≈550. Fitted by
       solving for peach's alpha over the base at a grid of background pixels;
       the residuals were within ±0.03 across the whole strip.

       This is where `peach` actually lives. It reads as an unused variable in
       the design-context scan only because it is a gradient stop inside a
       fill, and the SVG export drops those.

       Layer 2, the base: sampled down the left edge, where nothing overlaps.
       It darkens toward 23% and lifts again at the bottom, so three stops. */
    --gradient-hero:
      radial-gradient(
        ellipse 85% 72% at 100% 6%,
        rgb(246 211 177 / 0.7) 0%,
        rgb(246 211 177 / 0) 100%
      ),
      linear-gradient(
        180deg,
        #252541 0%,
        #1e1f3a 23%,
        #302d60 100%
      );

    /* Derived states. color-mix() replaces a primitive scale. */
    --color-brand-hover-from: color-mix(in oklab, var(--color-brand-from) 88%, #000);
    --color-brand-hover-to: color-mix(in oklab, var(--color-brand-to) 88%, #000);
    --color-border: color-mix(in oklab, var(--color-heading) 14%, transparent);
    --color-muted: color-mix(in oklab, var(--color-heading) 68%, var(--color-surface));

    /* ---------------------------------------------------------------------
       Typography
       Poppins. Weights in actual use: 200 italic, 300, 400, 500, 900.
       The Stilesheet only documents 300/400/500 — 200 italic carries the
       testimonial quotes and 900 the inline arrow glyphs.
       Desktop values are the Figma 1440 anchors.
       --------------------------------------------------------------------- */

    --font-sans: "Poppins", ui-sans-serif, system-ui, -apple-system,
                 "Segoe UI", Roboto, sans-serif;

    --weight-extralight: 200;
    --weight-light: 300;
    --weight-regular: 400;
    --weight-medium: 500;
    --weight-black: 900;

    /* Fluid between 320px and 1440px. Every clamp resolves to EXACTLY the
       Figma value at 1440, so desktop is pixel-identical to the design. */
    --text-4xl: clamp(2.5rem,   1.929rem + 2.857vw, 4.5rem);    /*  40 -> 72 */
    --text-3xl: clamp(2rem,     1.571rem + 2.143vw, 3.5rem);    /*  32 -> 56 */
    --text-xl:  clamp(1.5rem,   1.321rem + 0.893vw, 2.125rem);  /*  24 -> 34 */
    --text-lg:  clamp(1.25rem,  1.143rem + 0.536vw, 1.625rem);  /*  20 -> 26 */
    --text-md:  clamp(1.125rem, 1.054rem + 0.357vw, 1.375rem);  /*  18 -> 22, unused on Startseite */
    --text-sm:  1.0625rem;                                      /*  17 fixed, 91 uses */
    --text-xs:  0.625rem;                                       /*  10 fixed, unused on Startseite */
    /* figma: font-size/2xl. Confirmed from the Geld-Zurueck-Garantie codegen,
       where the FAQ chevrons use it. Earlier guessed at 44 when no page had
       yet used it; the file's real value is 50. */
    --text-2xl: clamp(1.75rem, 1.357rem + 1.9643vw, 3.125rem);  /*  28 -> 50 */

    /* Line heights.
       Figma expresses these in px. Converted to unitless ratios so they scale
       with the fluid font sizes, which keeps 1440 pixel-exact and degrades
       proportionally below it. Faithful, including the odd ones. */
    --leading-h1: 1.0556;      /* figma 76 / 72 */
    --leading-h2: 1;           /* figma 56 / 56 */
    --leading-h3: 0.9231;      /* figma 24 / 26, deliberately below 1 */
    --leading-h4: 2.5455;      /* figma 56 / 22, an unusually tall line box */
    --leading-lead: 1.0588;    /* figma 36 / 34 */
    --leading-body: 1.1176;    /* figma 19 / 17 */
    --leading-footnote: 1.9;   /* figma 19 / 10 */
    --leading-button: 1;       /* figma reports 100, which is wrong: verified
                                  against the real CTA pill in why-us */

    --tracking-tight: 0;       /* Figma letterSpacing is 0 on every style */
    --tracking-normal: 0;

    /* ---------------------------------------------------------------------
       Layout
       Measured from the frames: content starts at x=143 in a 1440 frame,
       three columns of 365px separated by 34px gaps.
       --------------------------------------------------------------------- */

    --wrapper: 72.75rem;                              /* 1164px measured */
    --gutter: clamp(1.25rem, 5vw, 2.5rem);
    --gap: clamp(1.25rem, 2.4vw, 2.125rem);           /* 34px at 1440 */

    /* ---------------------------------------------------------------------
       Spacing
       Figma defines exactly one spacing variable, spacing/xl = 68.
       The rest are fallback defaults; each section measures its own padding
       from its frame and overrides them.
       --------------------------------------------------------------------- */

    --space-xl: 4.25rem;                                     /* figma: spacing/xl, 68px */
    --space-section: clamp(4rem, 2.857rem + 5.714vw, 8rem);  /* fallback */
    --space-block: clamp(2rem, 1.43rem + 2.86vw, 4rem);      /* fallback */
    --space-element: clamp(1rem, 0.86rem + 0.71vw, 1.5rem);  /* fallback */
    --space-tight: 0.5rem;

    /* ---------------------------------------------------------------------
       Radius
       A complete scale exists in Figma. Every step is in real use.
       --------------------------------------------------------------------- */

    --radius-xs: 5px;      /* figma: radius/xs,  3 uses */
    --radius-sm: 10px;     /* figma: radius/sm,  8 uses */
    --radius-md: 15px;     /* figma: radius/md, 20 uses, the default */
    --radius-lg: 20px;     /* figma: radius/lg, 11 uses */
    --radius-xl: 30px;     /* figma: radius/xl,  9 uses */
    --radius-2xl: 55px;    /* figma: radius/2xl, 4 uses, pill buttons */

    /* ---------------------------------------------------------------------
       Elevation and motion
       One shadow in the entire design, used 24 times.
       --------------------------------------------------------------------- */

    --shadow-card: 0 4px 4px 0 rgb(0 0 0 / 0.25);

    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --duration-fast: 150ms;
    --duration-base: 300ms;
  }

  /* ---------------------------------------------------------------------
     Inverted context. Applied via data-variant="inverted" on a section root.
     Only tokens are remapped; no section CSS changes.
     --------------------------------------------------------------------- */
  [data-variant="inverted"] {
    --color-surface: #17203f;
    --color-text: #ffffff;
    --color-heading: #ffffff;
    --color-heading-alt: #ffffff;
    --color-border: color-mix(in oklab, #ffffff 18%, transparent);
    --color-muted: color-mix(in oklab, #ffffff 74%, #17203f);
  }

  @media (prefers-reduced-motion: reduce) {
    :root {
      --duration-fast: 0ms;
      --duration-base: 0ms;
    }
  }
}

/* ==========================================================================
   Above 1440: freeze and centre.

   Revised 2026-07-31. Nothing above the drawn width grows: the composition
   locks at the size it was designed at and centres, while section backgrounds
   keep running to the viewport edge. The extra width therefore reads as the
   design's own backdrop rather than as empty margin, and type never inflates
   past the size the designer chose.

   Scaling to 1920 was tried first and rejected on sight: 96px headings and a
   1.33x hero render did not look like the design, they looked like the design
   zoomed.
   ========================================================================== */

@layer tokens {
  :root {
    /* The drawn design width, and the offset that centres it once the
       viewport is wider. 0 at and below 1440. */
    --stage-w: min(100vw, 1440px);
    --stage-x: max(0px, (100vw - 1440px) / 2);
  }
}


/* base/fonts.css */
/* ==========================================================================
   Poppins, self-hosted.

   No Google Fonts CDN: serving fonts from Google on a German site is a GDPR
   liability, not a style preference.

   Two subsets per weight. They are COMPLEMENTARY, not nested: Google's `latin`
   subset is U+0000-00FF, which is where the German set lives (ä ö ü ß at
   U+00E4/00F6/00FC/00DF). `latin-ext` starts at U+0100 and carries none of
   them. Shipping only latin-ext would break every umlaut on the site.
   ========================================================================== */

@layer base {

  /* 300 normal — documented in the Stilesheet */

  @font-face {
    font-family: "Poppins";
    src: url("fonts/poppins-300-latin.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: "Poppins";
    src: url("fonts/poppins-300-latin-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;
  }

  /* 400 normal — documented in the Stilesheet */

  @font-face {
    font-family: "Poppins";
    src: url("fonts/poppins-400-latin.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: "Poppins";
    src: url("fonts/poppins-400-latin-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;
  }

  /* 500 normal — documented in the Stilesheet */

  @font-face {
    font-family: "Poppins";
    src: url("fonts/poppins-500-latin.woff2") format("woff2");
    font-weight: 500;
    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: "Poppins";
    src: url("fonts/poppins-500-latin-ext.woff2") format("woff2");
    font-weight: 500;
    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;
  }

  /* 200 italic — NOT in the Stilesheet. Carries every testimonial quote. */

  @font-face {
    font-family: "Poppins";
    src: url("fonts/poppins-200-italic-latin.woff2") format("woff2");
    font-weight: 200;
    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: "Poppins";
    src: url("fonts/poppins-200-italic-latin-ext.woff2") format("woff2");
    font-weight: 200;
    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;
  }

  /* 900 normal — NOT in the Stilesheet. Inline arrow glyphs only. */

  @font-face {
    font-family: "Poppins";
    src: url("fonts/poppins-900-latin.woff2") format("woff2");
    font-weight: 900;
    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: "Poppins";
    src: url("fonts/poppins-900-latin-ext.woff2") format("woff2");
    font-weight: 900;
    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;
  }

}


/* base/reset.css */
/* ==========================================================================
   Reset. Minimal and opinion-free: it removes browser defaults that fight the
   design and nothing else. Anything that changes how the page LOOKS belongs in
   typography.css or a section, not here.
   ========================================================================== */

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

  html {
    scroll-behavior: smooth;
    /* Must be on the root element, not just body. Several sections bleed past
       the right edge by design (the hero figure reaches x=1562, cards run off
       the frame). Clipping only on body still lets the root grow, which raises
       a horizontal scrollbar, which narrows the viewport by ~15px, which is
       enough to wrap the 7-logo client row onto a second line and shift every
       section below it by 116px. One missing declaration, a whole-page layout
       shift.

       `clip` rather than `hidden`: hidden would make this a scroll container
       and break `position: sticky` in descendants. */
    overflow-x: clip;
  }

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

  body {
    margin: 0;
    min-height: 100svh;
    /* Sections are full-bleed and several contain shapes that overhang the
       viewport horizontally. Clipping here is what keeps the 320px
       no-horizontal-scroll rule true without every section defending itself. */
    overflow-x: clip;
  }

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

  img,
  video {
    height: auto;
  }

  input,
  button,
  textarea,
  select {
    font: inherit;
    color: inherit;
  }

  button {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
  }

  ul[class],
  ol[class] {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  /* Sections own their vertical rhythm as padding. A stray margin here would
     collapse against a neighbour and break order independence. */
  section {
    margin: 0;
  }
}

@layer utilities {
  /* The measured content column: 1164px wide, centred, from the Figma frames. */
  .wrapper {
    width: 100%;
    max-width: var(--wrapper);
    margin-inline: auto;
    padding-inline: var(--gutter);
  }
}


/* base/typography.css */
/* ==========================================================================
   Typography. The nine Figma text styles, mapped to elements and utilities.
   Headings are styled at element level so markup stays clean: sections do not
   put a class on every h2. Utilities exist only for the paragraph variants,
   which genuinely vary within a section.

   Figma style      -> here
   H1               -> h1
   H2               -> h2
   H3               -> h3
   H4               -> h4
   <p>headline      -> .text-lead     (Focustext, 34px)
   <p>medium        -> p              (default body, 17px regular)
   <p>light         -> .text-light    (17px, weight 300)
   <p>button        -> .text-button   (17px, weight 500)
   <p>fussnote      -> .text-footnote (10px)

   FIDELITY FIRST. Values reproduce Figma exactly, including line heights that
   look wrong (H3 at 0.92, H4 at 2.55, body at 1.12). Do not "improve" them
   here. If a value should change, it changes in Figma first.
   ========================================================================== */

@layer base {

  /* @font-face declarations live in base/fonts.css. */

  /* ---------------------------------------------------------------------- */

  html {
    font-family: var(--font-sans);
    font-size: 100%;              /* never override the user's root size */
    -webkit-text-size-adjust: 100%;
  }

  body {
    font-size: var(--text-sm);
    font-weight: var(--weight-regular);
    line-height: var(--leading-body);
    color: var(--color-text);
    background-color: var(--color-surface);
  }

  /* German compounds overflow narrow viewports. Applied only below the
     desktop range so 1440 rendering stays identical to Figma. */
  @media (width < 1024px) {
    body {
      hyphens: auto;
      -webkit-hyphens: auto;
      overflow-wrap: break-word;
    }
    :lang(de) {
      hyphenate-limit-chars: 8 4 4;
    }
  }

  /* No text-wrap: balance or pretty anywhere.
     The Figma copy contains U+2028 line separators, meaning the designer set
     line breaks by hand. Those are reproduced as <br class="u-br-lg"> and
     browser rebalancing would fight them. */

  h1, h2, h3, h4 {
    font-weight: var(--weight-regular);
    color: var(--color-heading);
    letter-spacing: var(--tracking-tight);
    margin-block: 0;
  }

  h1 {
    font-size: var(--text-4xl);
    line-height: var(--leading-h1);
  }

  h2 {
    font-size: var(--text-3xl);
    line-height: var(--leading-h2);
  }

  h3 {
    font-size: var(--text-lg);
    line-height: var(--leading-h3);
  }

  h4 {
    font-size: var(--text-md);
    line-height: var(--leading-h4);
  }

  p {
    margin-block: 0;
    /* No max-width. Figma sets explicit text-box widths per node and those
       are reproduced in the section CSS. */
  }

  /* TBD: the design file does not define a distinct link colour. Measure the
     actual link styling during extraction and replace this. Inheriting for
     now so nothing invented leaks into the build. */
  a {
    color: inherit;
    text-underline-offset: 0.2em;
    transition: color var(--duration-fast) var(--ease-out);
  }

  :focus-visible {
    outline: 2px solid var(--color-accent-deep);
    outline-offset: 3px;
  }

  ul, ol {
    margin-block: 0;
    padding-inline-start: 1.25em;
  }

  strong, b {
    font-weight: var(--weight-medium);
  }
}

@layer utilities {

  /* Figma "<p>headline" / Focustext, 34 / 36 */
  .text-lead {
    font-size: var(--text-xl);
    font-weight: var(--weight-regular);
    line-height: var(--leading-lead);
  }

  /* Figma "<p>light", 17 / 19 weight 300 */
  .text-light {
    font-weight: var(--weight-light);
  }

  /* Figma "<p>button", 17px weight 500 */
  .text-button {
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    line-height: var(--leading-button);
    letter-spacing: var(--tracking-normal);
  }

  /* Figma "<p>fussnote", 10 / 19 weight 300 */
  .text-footnote {
    font-size: var(--text-xs);
    font-weight: var(--weight-light);
    line-height: var(--leading-footnote);
  }

  /* The signature brand treatment: gradient-filled text. Used 34 times on
     Startseite, on partial headline phrases, stat numbers, and role labels.

     Wrap only the coloured RUN, never the whole heading, because the design
     gradients a phrase inside a longer line:
       <h2>Unser perfektionierter Ablauf für maximale
           <span class="u-gradient-text">Effizienz &amp; Leads</span></h2>

     background-clip: text has no accessible-name effect, and the text stays
     selectable and searchable. Falls back to the solid end colour where
     background-clip is unsupported. */
  .u-gradient-text {
    background-image: var(--gradient-brand);
    color: var(--color-brand-to);
  }

  @supports (background-clip: text) or (-webkit-background-clip: text) {
    .u-gradient-text {
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
    }
  }

  /* Testimonial quote body: Poppins 200 italic. */
  .text-quote {
    font-weight: var(--weight-extralight);
    font-style: italic;
  }

  /* Reproduces a designer's manual line break (U+2028 in the Figma copy).
     Visible at the desktop widths the design was drawn for, collapsed below,
     where the original break would land in the wrong place. */
  .u-br-lg {
    display: none;
  }

  @media (width >= 1024px) {
    .u-br-lg {
      display: inline;
    }
  }

  .visually-hidden:not(:focus):not(:active) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}


/* sections/site-header/section.css */
/* ==========================================================================
   Section: site-header (Kopfbereich)
   Figma band y 0..120 in a 1440 frame, content bleeding to y=137.

   This section OVERLAYS the hero. It is absolutely positioned at the document
   top, over the hero's gradient, and carries no background of its own because
   the design draws none. The hero starts its own content at y=214 to leave
   room for it.

   Measured anchors, all reproduced at 1440:
     row top             y = 84   (top edge of the seal, the tallest element)
     content insets      x = 143 left, 69 right (bars end at 1371)
     trust icons         x = 143 (36x36), 408 (105x33), 690 (53x53)
     trust texts         x = 191, 524, 743 — 17/19 Poppins Light, white
     contact link        x = 1065, y = 97, box 211 wide, centred,
                         17 Poppins Medium, line box 24 ("normal")
     hamburger bars      x = 1315, y = 88 / 104 / 119, 56 x 5, radius 5

   Two sub-pixel deviations, taken deliberately so the row needs no per-item
   positioning and survives a repeater with a different number of items:
     - the three icons and the three text blocks are centred on one 53px row
       instead of being placed individually. Worst case 1.5px, on the first
       line of the trust texts.
     - the hamburger bars are distributed in a 36px box (gaps 10.5/10.5)
       rather than Figma's 11/10, so the middle bar sits 0.5px high.
   ========================================================================== */

@layer sections {
  .site-header {
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    /* Above the hero, which paints a background and isolates itself. */
    z-index: 10;
    color: var(--color-on-dark);
    /* The row starts at y=84. No bottom padding: the section is out of flow,
       so it owns no rhythm — but it also never imposes any. */
    padding-block: 84px 0;
    /* 143/1440 = 9.931vw, 69/1440 = 4.792vw. Exact at 1440. */
    padding-inline:
      calc(var(--stage-x) + clamp(1.25rem, 9.931vw, 143px))
      calc(var(--stage-x) + clamp(1.25rem, 4.792vw, 69px));
  }

  .site-header__inner {
    display: flex;
    align-items: flex-start;
    /* Contact box ends at 1276, bars start at 1315. */
    column-gap: 39px;
  }

  /* Six columns, one per element, each track the exact distance to the next
     element's left edge: 143→191→408→524→690→743. Reproducing the measured
     x positions this way avoids inventing a uniform icon-to-text gap, which
     the design does not have (it is 12, 11 and 0). */
  .site-header__trust {
    display: grid;
    grid-template-columns: 48px 217px 116px 166px 53px auto;
    align-items: center;
  }

  /* Subgrid keeps the item as a real <li> (list semantics survive) while its
     icon and text land on the parent's column edges. */
  .site-header__trust-item {
    display: grid;
    grid-column: span 2;
    grid-template-columns: subgrid;
    align-items: center;
  }

  @supports not (grid-template-columns: subgrid) {
    /* Fallback: the measured 12/11/0 gaps become one uniform 12px. */
    .site-header__trust-item {
      display: flex;
      gap: 12px;
    }
  }

  /* Sized by the width/height attributes, which are the Figma box sizes. */
  .site-header__trust-icon {
    flex: none;
  }

  .site-header__trust-text {
    font-size: var(--text-sm);
    font-weight: var(--weight-light);
    line-height: var(--leading-body);
    color: var(--color-on-dark);
  }

  .site-header__contact {
    /* Pushed to the right edge of the row; the 39px column gap then places it
       exactly 1276→1315 from the bars. */
    margin-inline-start: auto;
    margin-block-start: 13px;      /* row top 84 → text box top 97 */
    inline-size: 211px;            /* Figma text box, centred inside */
    flex: none;
    text-align: center;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    /* Figma: lineHeight "normal", node height 24 on a 17px font. This is NOT
       the <p>button style (which reports 100) — measured on this node. */
    line-height: calc(24 / 17);
    color: var(--color-on-dark);
    text-decoration: none;
  }

  /* Not in the design: links have no hover state anywhere in the file. An
     underline is the least invented thing available. */
  .site-header__contact:hover,
  .site-header__contact:focus-visible {
    text-decoration: underline;
  }

  .site-header__toggle {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    flex: none;
    inline-size: 56px;
    block-size: 36px;              /* 88 → 124, the three bars */
    margin-block-start: 4px;       /* row top 84 → first bar 88 */
    /* Stays above the drawer scrim so it can double as the close control. */
    position: relative;
    z-index: 2;
    /* Bar geometry in the open state, read by the bars below. */
    --bar-shift: 0px;
    --bar-turn: 0deg;
    --bar-mid: 1;
  }

  .site-header__toggle[aria-expanded="true"] {
    --bar-shift: 15.5px;
    --bar-turn: 45deg;
    --bar-mid: 0;
  }

  .site-header__bar {
    block-size: 5px;
    border-radius: var(--radius-xs);
    background-color: var(--color-on-dark);
    transition:
      translate var(--duration-base) var(--ease-out),
      rotate var(--duration-base) var(--ease-out),
      scale var(--duration-base) var(--ease-out);
  }

  /* Closed: three bars. Open: an X. The middle bar collapses with scale, not
     opacity, because a section stylesheet never contains opacity:0. */
  .site-header__bar:first-child {
    translate: 0 var(--bar-shift);
    rotate: var(--bar-turn);
  }

  .site-header__bar:nth-child(2) {
    scale: var(--bar-mid) 1;
  }

  .site-header__bar:last-child {
    translate: 0 calc(-1 * var(--bar-shift));
    rotate: calc(-1 * var(--bar-turn));
  }

  /* Indigo on this gradient is close to invisible, so the focus ring is white
     here. Structural accessibility, not a design change. */
  .site-header__contact:focus-visible,
  .site-header__toggle:focus-visible,
  .site-header__nav-link:focus-visible {
    outline-color: var(--color-on-dark);
  }

  /* ------------------------------------------------------------------
     Drawer. INVENTED — the Figma file contains a hamburger at every width
     and no open state anywhere. Kept to tokens the design already uses:
     dark-navy surface, white text, the shared duration and easing.
     ------------------------------------------------------------------ */

  .site-header__drawer {
    position: fixed;
    inset: 0;
    z-index: 1;
    /* Closed state without opacity:0 — visibility also takes the panel out of
       the tab order and the accessibility tree while it is shut.
       Opening flips visibility immediately (0s, no delay) so the first link is
       focusable in the same tick; closing holds it until the slide is done. */
    visibility: hidden;
    background-color: transparent;
    --drawer-x: 100%;
    transition:
      visibility 0s linear var(--duration-base),
      background-color var(--duration-base) var(--ease-out);
  }

  .site-header__drawer[data-open="true"] {
    visibility: visible;
    background-color: rgb(0 0 0 / 0.5);
    --drawer-x: 0%;
    transition:
      visibility 0s linear 0s,
      background-color var(--duration-base) var(--ease-out);
  }

  .site-header__panel {
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0;
    inline-size: min(420px, 100%);
    padding: 144px 40px 40px;      /* clears the hamburger at 1440 */
    overflow-y: auto;
    background-color: var(--color-surface-dark);
    translate: var(--drawer-x) 0;
    transition: translate var(--duration-base) var(--ease-out);
  }

  .site-header__nav-list {
    display: grid;
    gap: 24px;
  }

  .site-header__nav-link {
    font-size: var(--text-lg);
    line-height: var(--leading-body);
    color: var(--color-on-dark);
    text-decoration: none;
  }

  .site-header__nav-link:hover,
  .site-header__nav-link:focus-visible {
    text-decoration: underline;
  }

  /* ------------------------------------------------------------------
     Below 1440 there is no design. Decisions taken here:

     1360px is where the drawn row stops fitting: 143+69 of inset plus the
     796px trust row, the 211px contact box, the 56px bars and two 39px gaps
     need ~1141px of content width. Under that the header becomes two rows —
     contact and menu button on top, trust marks underneath — which is the
     only arrangement that still clears the hero's own top padding (214px
     down to 160px below 1024).

     The trust row never wraps: it stays a single line and scrolls
     horizontally instead. Wrapping it to two lines makes the header ~186px
     tall, which would collide with the hero heading on small screens.
     ------------------------------------------------------------------ */

  @media (width < 1360px) {
    .site-header {
      padding-block: 24px 0;
    }

    .site-header__inner {
      flex-wrap: wrap;
      align-items: center;
      row-gap: 12px;
      column-gap: 20px;
    }

    .site-header__trust {
      order: 1;                    /* onto its own line, under the top row */
      flex: 1 0 100%;
      display: flex;
      flex-wrap: nowrap;
      gap: 32px;
      overflow-x: auto;
      overscroll-behavior-inline: contain;
    }

    .site-header__trust-item {
      display: flex;
      flex: none;
      align-items: center;
      gap: 12px;
    }

    .site-header__contact {
      inline-size: auto;
      margin-block-start: 0;
    }

    .site-header__toggle {
      margin-block-start: 0;
    }

    .site-header__panel {
      padding-block-start: 96px;
    }
  }
}


/* sections/hero-page/section.css */
/* ==========================================================================
   Section: hero-page
   The interior-page hero. Simpler than the Startseite hero: a title and one
   decorative render, no stats and no CTA.

   Figma frame "Agentur" (213:32), band y 0..767 in a 1440 frame.

   Measured anchors, reproduced exactly at 1440:
     background     the same 1439 x 767 gradient the Startseite hero uses,
                    so it is the shared --gradient-hero token, not a copy
     h1             x = 143, y = 245, w = 532, 72 / 76, white,
                    "TOP-Websites" carries the brand gradient
     figure         box x = 350, y = -179, 1258.958 x 1173.697
                    inner render 1015 x 866 rotated -21.13deg, img at 117.21%

   The site-header overlays this section, exactly as it overlays the Startseite
   hero, which is why the top padding clears it.
   ========================================================================== */

@layer sections {
  .hero-page {
    position: relative;
    isolation: isolate;
    background-image: var(--gradient-hero);
    color: var(--color-on-dark);
    /* Title line box opens at 245. The bottom padding is a floor for narrow
       viewports only: at 1440 the min-height below governs, which is what lets
       one section serve titles of three, four and five lines without each page
       needing its own bottom value. Tallest content is Blog's at 670. */
    padding-block: 245px 64px;
    padding-inline:
      calc(var(--stage-x) + clamp(1.25rem, 9.9306vw, 143px))
      calc(var(--stage-x) + 0px);
    min-block-size: 767px;
  }

  .hero-page__title {
    position: relative;
    z-index: 1;
    /* The drawn text box, per page. Agentur is 532 wide, Geld-Zurueck-Garantie
       725; both start at x=143. */
    max-inline-size: var(--title-measure, 532px);
    /* Figma paints ONE gradient across the whole text node, so an accent that
       falls on a later line restarts at the cyan end rather than continuing
       where the previous line stopped. Putting the gradient on the heading and
       clipping it to the glyphs reproduces that; scoping it to the accent span
       instead would map the ramp across the span's own box and render the
       second fragment violet. The white runs stay opaque and paint over it. */
    background-image: var(--gradient-brand);
    font-size: var(--text-4xl);
    line-height: var(--leading-h1);
    color: var(--color-on-dark);
  }

  .hero-page__accent {
    color: var(--color-brand-to);
  }

  @supports (background-clip: text) or (-webkit-background-clip: text) {
    .hero-page__title {
      -webkit-background-clip: text;
      background-clip: text;
    }

    .hero-page__accent {
      color: transparent;
    }
  }

  /* Figma centres this in a 599px box, but the rendered line sits flush with
     the h1 at x=143, so it is left-aligned here to match what is drawn. */
  .hero-page__subtitle {
    position: relative;
    z-index: 1;
    /* Title closes at 473 (three lines of 76 from 245); subline opens at 532. */
    margin-block-start: 59px;
    font-size: var(--text-xl);
    font-weight: var(--weight-light);
    font-style: italic;
    line-height: var(--leading-lead);
    color: var(--color-on-dark);
  }

  .hero-page[data-variant="wide"] {
    --title-measure: 725px;
  }

  /* Same pill as the Startseite hero: the gradient sits at 70% but the label
     does not, so the fill lives on a pseudo-element. */
  .hero-page__cta {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 195px;
    block-size: 37px;
    /* Blog's title runs to four lines, closing at 549; the pill opens at 633. */
    margin-block-start: 84px;
    border-radius: var(--radius-2xl);
    color: var(--color-on-dark);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    line-height: var(--leading-button);
    text-decoration: none;
    isolation: isolate;
    z-index: 1;
  }

  .hero-page__cta::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background-image: var(--gradient-brand);
    opacity: 0.7;
    transition: opacity var(--duration-fast) var(--ease-out);
  }

  .hero-page__cta:hover::before,
  .hero-page__cta:focus-visible::before {
    opacity: 1;
  }

  .hero-page__figure {
    position: absolute;
    /* Drawn at 350 / -179. Frozen there and shifted onto the centred stage
       once the viewport is wider than the design. */
    inset-block-start: -179px;
    inset-inline-start: calc(var(--stage-x) + 350px);
    inline-size: 1258.958px;
    aspect-ratio: 1258.958 / 1173.697;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 0;
  }

  /* The rotation lives on its own element so it cannot become a transform on
     a positioned ancestor, which would turn that ancestor into a containing
     block and quietly re-anchor the figure. */
  .hero-page__figure-frame {
    flex: none;
    inline-size: 80.622%;    /* 1015 / 1258.958 */
    aspect-ratio: 1015 / 866;
    rotate: -21.13deg;
    display: block;
    overflow: hidden;
  }

  .hero-page__figure-frame img {
    inline-size: 100%;
    block-size: 117.21%;     /* the source overflows its frame, as drawn */
    max-inline-size: none;
    object-fit: cover;
  }

  /* ------------------------------------------------------------------
     Below 1440 there is no comp. Decisions taken here:
       - the figure stops being an overlay and becomes a block, because a
         1258px render behind five lines of 72px type is unreadable once
         the column narrows
       - the hero's fixed height is released so it fits its content
     ------------------------------------------------------------------ */

  @media (width < 64rem) {
    .hero-page {
      padding-block: 160px 64px;
      min-block-size: 0;
      overflow: hidden;
    }

    .hero-page__title {
      max-inline-size: none;
    }

    .hero-page__accent {
    color: var(--color-brand-to);
  }

  @supports (background-clip: text) or (-webkit-background-clip: text) {
    .hero-page__title {
      -webkit-background-clip: text;
      background-clip: text;
    }

    .hero-page__accent {
      color: transparent;
    }
  }

  /* Figma centres this in a 599px box, but the rendered line sits flush with
     the h1 at x=143, so it is left-aligned here to match what is drawn. */
  .hero-page__subtitle {
    position: relative;
    z-index: 1;
    /* Title closes at 473 (three lines of 76 from 245); subline opens at 532. */
    margin-block-start: 59px;
    font-size: var(--text-xl);
    font-weight: var(--weight-light);
    font-style: italic;
    line-height: var(--leading-lead);
    color: var(--color-on-dark);
  }

  .hero-page[data-variant="wide"] {
    --title-measure: 725px;
  }

  /* Same pill as the Startseite hero: the gradient sits at 70% but the label
     does not, so the fill lives on a pseudo-element. */
  .hero-page__cta {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 195px;
    block-size: 37px;
    /* Blog's title runs to four lines, closing at 549; the pill opens at 633. */
    margin-block-start: 84px;
    border-radius: var(--radius-2xl);
    color: var(--color-on-dark);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    line-height: var(--leading-button);
    text-decoration: none;
    isolation: isolate;
    z-index: 1;
  }

  .hero-page__cta::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background-image: var(--gradient-brand);
    opacity: 0.7;
    transition: opacity var(--duration-fast) var(--ease-out);
  }

  .hero-page__cta:hover::before,
  .hero-page__cta:focus-visible::before {
    opacity: 1;
  }

  .hero-page__figure {
      position: static;
      inline-size: 100%;
      margin-block-start: 32px;
    }
  }
}


/* sections/blog-list/section.css */
/* ==========================================================================
   Section: blog-list
   Figma frame "Blog" (218:358), band y 767..2225.

   Measured anchors, reproduced exactly at 1440:
     h2         x = 143, y = 915, 56 / 56, #1b1d36, "Wissenshub" gradient
     intro      x = 143, y = 1014, two paragraphs, 17 / 19 light
     cards      x = 142 / 538 / 934, rows at y = 1125 and 1679,
                365 x 489, radius 15, white at 0.8, --shadow-card
     photo      365 x 244, top corners rounded, sitting 9px above the card
     title      +26 inside, y = 1394, 26 / 24 dark-navy, 313 wide
     excerpt    +26 inside, y = 1456, 272 wide, 17 / 19 light
     more link  +26 inside, y = 1571, 17 / 19, brand gradient
     ornaments  left  box x = -191, y = 1039, 956.248 x 909.471,
                      inner 717.398 x 786.324 rotated 106.32deg
                right box x =  864, y = 1689, 737.436 x 871.456,
                      inner 839.688 x 698.931 rotated -87.32deg

   The photo overhangs the card's top by 9px in the design (1116 against 1125),
   which is why it is positioned rather than simply stacked.

   Every card carries identical copy: it is placeholder standing in for six
   real posts. Reproduced verbatim and flagged in section.json.
   ========================================================================== */

@layer sections {
  .blog-list {
    position: relative;
    /* No background: both ornaments overhang neighbouring sections, and a
       white fill here would slice them. See CONVENTIONS section 3. */
    padding-block: 148px 57px;
    padding-inline:
      calc(var(--stage-x) + clamp(1.25rem, 9.8611vw, 142px))
      calc(var(--stage-x) + clamp(1.25rem, 9.7917vw, 141px));
  }

  .blog-list__title,
  .blog-list__intro,
  .blog-list__grid {
    position: relative;
    z-index: 1;
  }

  .blog-list__title {
    /* Heading and intro sit 1px inside the card grid's left edge (143 vs 142). */
    margin-inline-start: 1px;
    max-inline-size: 881px;
    color: var(--color-heading-alt);
  }

  .blog-list__intro {
    margin-block-start: 43px;   /* h2 closes at 971, intro opens at 1014 */
    margin-inline-start: 1px;
  }

  .blog-list__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 365px));
    /* Card left edges 142 / 538 / 934 give a uniform 31px gutter; rows open at
       1125 and 1679, so 65px between them. */
    column-gap: 31px;
    row-gap: 65px;
    /* Intro closes at 1052 (two lines of 19), cards open at 1125. */
    margin-block-start: 73px;
  }

  /* Note: .blog-list__post deliberately has no padding for the photo's 9px
     overhang. The photo is offset out of the card and simply overflows;
     reserving space here as well would count the overhang twice and add 9px
     to every row. */

  .blog-list__link {
    position: relative;
    display: block;
    block-size: 489px;
    /* Card opens at 1125, its title at 1394. */
    padding: 269px 26px 0;
    border-radius: var(--radius-md);
    background-color: rgb(255 255 255 / 0.8);
    box-shadow: var(--shadow-card);
    color: inherit;
    text-decoration: none;
  }

  .blog-list__photo {
    position: absolute;
    /* Figma wraps this in scaleY(-1) + rotate(180deg), which nets to a
       horizontal flip. Dropping it mirrors the photo. */
    scale: -1 1;
    inset-block-start: -9px;
    inset-inline: 0;
    inline-size: 100%;
    block-size: 244px;
    border-start-start-radius: var(--radius-md);
    border-start-end-radius: var(--radius-md);
    object-fit: cover;
  }

  .blog-list__post-title {
    color: var(--color-surface-dark);
    max-inline-size: 313px;
  }

  .blog-list__excerpt {
    margin-block-start: 14px;   /* title closes at 1442, excerpt opens at 1456 */
    max-inline-size: 272px;
  }

  .blog-list__more {
    display: inline-block;
    /* Excerpt closes at 1532 (four lines), the link opens at 1571. */
    margin-block-start: 39px;
    font-size: var(--text-sm);
    line-height: var(--leading-body);
  }

  .blog-list__link:hover .blog-list__more,
  .blog-list__link:focus-visible .blog-list__more {
    text-decoration: underline;
    text-underline-offset: 0.2em;
  }

  /* --- ornaments -------------------------------------------------------- */

  .blog-list__ornament {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 0;
  }

  .blog-list__ornament[data-side="left"] {
    /* Enters from off-canvas, so it stays on the viewport edge rather than
       the centred stage. */
    inset-block-start: 272px;      /* 1039 - 767 */
    inset-inline-start: -191px;
    inline-size: 956.248px;
    aspect-ratio: 956.248 / 909.471;
  }

  .blog-list__ornament[data-side="right"] {
    inset-block-start: 922px;      /* 1689 - 767 */
    inset-inline-start: calc(var(--stage-x) + 864px);
    inline-size: 737.436px;
    aspect-ratio: 737.436 / 871.456;
  }

  .blog-list__ornament-frame {
    flex: none;
    display: block;
    overflow: hidden;
  }

  .blog-list__ornament[data-side="left"] .blog-list__ornament-frame {
    inline-size: 75.022%;          /* 717.398 / 956.248 */
    aspect-ratio: 717.398 / 786.324;
    rotate: 106.32deg;
  }

  .blog-list__ornament[data-side="right"] .blog-list__ornament-frame {
    inline-size: 113.865%;         /* 839.688 / 737.436 */
    aspect-ratio: 839.688 / 698.931;
    rotate: -87.32deg;
  }

  .blog-list__ornament-frame img {
    max-inline-size: none;
    object-fit: cover;
  }

  .blog-list__ornament[data-side="left"] .blog-list__ornament-frame img {
    inline-size: 129.3%;
    block-size: 117.96%;
  }

  .blog-list__ornament[data-side="right"] .blog-list__ornament-frame img {
    inline-size: 100%;
    block-size: 120.14%;
  }

  /* ------------------------------------------------------------------
     Below 1440 there is no comp. Decisions taken here:
       - three columns to two at 64rem, then one at 40rem
       - the card's fixed 489px height is released so a real excerpt can
         wrap without overflowing, and the photo returns to the flow
       - both ornaments are dropped below 64rem: their placement is a
         function of the 1440 composition and they land on the cards
     ------------------------------------------------------------------ */

  @media (width < 64rem) {
    .blog-list {
      padding-block: 96px 64px;
    }

    .blog-list__grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .blog-list__link {
      block-size: auto;
      padding-block: 0 26px;
      display: flex;
      flex-direction: column;
    }

    .blog-list__photo {
      position: static;
      display: block;
      margin-block-end: 34px;
      margin-inline: -26px;
      inline-size: calc(100% + 52px);
    }

    .blog-list__ornament {
      display: none;
    }
  }

  @media (width < 40rem) {
    .blog-list__grid {
      grid-template-columns: minmax(0, 1fr);
    }
  }
}


/* sections/contact-cta/section.css */
/* ==========================================================================
   Section: contact-cta
   Figma band y 5760..6632 in a 1440 frame. The extractor's band stops at 6400,
   but the grey rect this section owns runs to 6632, which is the bottom edge of
   the page frame. There is no footer node anywhere in the file, so the section
   owns the page's last 872px outright.

   Measured anchors, all reproduced exactly at 1440:
     content inset      x = 105 left, 114 right  (1221 between = banner width)
     h2                 x = 105, y = 5838, w = 881, 56/56, #1b1d36
                        "Sie erreichbar!" gradient-filled, break after "für"
     banner             x = 105, y = 6020, 1221 x 286, radius 15, --shadow-card
     banner title       x = 179, y = 6092, 34/36, white
     banner text        x = 179, y = 6147, 17/19, white
     pill 1             x = 179, y = 6191, 195 x 37, radius 55, gradient @ 70%
     pill 2             x = 392, y = 6191, 159 x 37   (18px gap)
     portrait back      x = 726, y = 5819, 347 x 487  (bottom = banner bottom)
     portrait front     x = 811, y = 5807, 606 x 499  (bottom = banner bottom)
     grey band          x = -53, y = 6163, 1503 x 469, radius 15, #f2f2f2
     3D glyph           bbox x = 746.91, y = 5002.91, 1291.083 square
                        (a 927px square rotated 125.01deg)
   ========================================================================== */

@layer sections {
  .contact-cta {
    position: relative;
    /* Deliberately NOT a stacking context, and deliberately no background.

       The 3D glyph bleeds 757px up into `testimonials` and must paint BEHIND
       that section's cards, as drawn. That only works if it can reach the
       page's negative z layer, which `isolation: isolate` would seal off and
       a background on this root would paint over. The body's white shows
       through instead.

       So: never add isolation, z-index, transform, filter or opacity to this
       element. Any of them re-traps the glyph and it jumps back in front of
       the testimonial text. */
    /* Top: the h2 text box sits 78px below the band top (5838 - 5760).
       Bottom: the banner ends at 6306 and the page frame at 6632, so 326px of
       empty grey follows it. That gap is reproduced, not trimmed — it is the
       missing footer's footprint and it is flagged in the report. */
    padding-block: 78px 326px;
    /* Asymmetric by design: 105 left, 114 right, which leaves exactly the
       1221px the banner is drawn at. 105/1440 = 7.292vw, 114/1440 = 7.917vw. */
    padding-inline:
      calc(var(--stage-x) + clamp(1.25rem, 7.292vw, 105px))
      calc(var(--stage-x) + clamp(1.25rem, 7.917vw, 114px));
  }

  /* ------------------------------------------------------------------
     Background layers
     ------------------------------------------------------------------ */

  .contact-cta__band {
    position: absolute;
    /* Behind everything in the section but still in front of the section's own
       white background: negative z-index paints after the stacking context's
       background, not before it. */
    z-index: -1;
    /* Anchored to the BOTTOM, not the top. The band ends on the page frame's
       bottom edge, and 469 - 326 puts its top edge 143px below the banner's
       top edge at every width, which is the crossing the design draws. */
    inset-block-end: 0;
    block-size: 469px;
    /* x = -53 .. 1450 in a 1440 frame, kept proportional so the bleed survives
       narrower viewports. body has overflow-x: clip. */
    inset-inline-start: -3.681%;
    inline-size: 104.375%;
    border-radius: var(--radius-md);
    background-color: var(--color-surface-muted);
  }

  .contact-cta__shape {
    /* Its bounding box starts 757px above this section, so the glyph bleeds up
       into whichever section precedes this one. The overhang is in vw
       (757/1440 = 52.569vw) so it stays proportional below 1440, and capped in
       px above it so the bleed never grows past what the comp draws. */
    position: absolute;
    /* Negative layer: paints above the page background but behind the block
       content of every section, which is what puts it behind the testimonial
       cards as drawn. */
    z-index: -1;
    inset-block-start: max(-757px, -52.569vw);
    inset-inline-start: 51.869%;                 /* 746.91 / 1440 */
    inline-size: min(89.658%, 1291.083px);       /* 1291.083 / 1440 */
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
  }

  .contact-cta__shape img {
    inline-size: 71.8%;            /* 927 / 1291.083 */
    block-size: auto;
    aspect-ratio: 1;
    transform: rotate(125.01deg);
  }

  /* ------------------------------------------------------------------
     Heading
     ------------------------------------------------------------------ */

  .contact-cta__title {
    position: relative;
    z-index: 1;
    /* Figma text node 190:60. #1b1d36, not the dark-navy every other heading
       uses — a near-duplicate that CONVENTIONS records as a design accident.
       Reproduced. */
    max-inline-size: 881px;
    color: var(--color-heading-alt);
  }

  .contact-cta__title-accent {
    /* Figma runs the gradient across the WHOLE 881px text node, not across the
       coloured run: measured on the render, the green channel at x=490 is 147,
       which is the 881px ramp at 43.7% and not the ~405px run's own ramp. The
       run starts on the text box's left edge, so sizing its background to
       881px reproduces the exact fill. */
    background-size: 881px 100%;
  }

  /* ------------------------------------------------------------------
     Banner
     ------------------------------------------------------------------ */

  .contact-cta__banner {
    position: relative;
    /* h2 bottom is 78 + 2 x 56 = 190; the banner starts at 260. */
    margin-block-start: 70px;
    /* 72 top / 78 bottom and 74 either side reproduce 286px of height and put
       the content column's left edge on x=179. */
    padding-block: 72px 78px;
    padding-inline: clamp(1.25rem, 5.139vw, 74px);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    color: var(--color-on-dark);
    /* The fill is NOT a left-to-right gradient, and Figma's own code export
       emits no fill for this node at all — see the report. It is a 2D field,
       so it is rebuilt from the reference render as three layers:

         1. base ramp (90deg), sampled along the banner's bottom edge, where
            the other two layers have died out;
         2. a dark blob over the upper-left quadrant, which is what pulls the
            ramp down to #171a31 at 15% along the TOP edge while the bottom
            edge stays flat at #2f2f60;
         3. a warm highlight bleeding in from the top-right, where a studio
            backdrop lifts behind the portraits.

       Every stop is a measured value except between 53% and 90%, which the
       portraits cover completely and which is interpolated. Residual error is
       under 8 levels everywhere except a patch around x=300 y=440 (~20 in the
       blue channel), and that patch sits behind the first pill. */
    /* The banner fill. Node 190:43 exports as radius + shadow only: the fill
       is a 2D field Figma's codegen cannot express, so it arrived with no
       colour at all.

       This is the real thing, exported from the node at 2x and cropped to the
       drawn 1221 x 286 (the raw export is 1229 x 294 because it includes the
       drop shadow's 4px blur and 4px y-offset).

       It replaces three measured gradient layers whose x 53-90% band was pure
       interpolation, because the portraits cover it completely and there was
       nothing to sample there. */
    background-image: url("img/cta-banner-fill.png");
    background-size: 100% 100%;
    background-position: left top;
    background-repeat: no-repeat;
  }

  .contact-cta__banner-body {
    position: relative;
    z-index: 1;
    /* 498px at 1440 (the widest of the two Figma text boxes), expressed as a
       fraction of the banner's content box (1073px) so that as the banner
       narrows the copy shrinks with it and never slides under the portraits,
       whose left edge sits at 50.86% of the banner. */
    max-inline-size: 46.412%;
  }

  .contact-cta__banner-title {
    /* Figma centres this text in a 143..641 box, which happens to land its left
       edge on 179 — the same x as the line below it and the first pill.
       Reproduced as left-aligned from 179 so a longer CMS string cannot drift
       off that edge. */
    color: var(--color-on-dark);
  }

  .contact-cta__banner-text {
    /* Title line box ends at 6128, this one starts at 6147. */
    margin-block-start: 19px;
    color: var(--color-on-dark);
  }

  /* ------------------------------------------------------------------
     The two CTAs. Same pill treatment as the hero: the gradient sits at 70%
     opacity in Figma and the label does not, so the fill lives on a
     pseudo-element and the text stays fully opaque.
     ------------------------------------------------------------------ */

  .contact-cta__actions {
    display: flex;
    flex-wrap: wrap;
    /* 392 - (179 + 195) */
    gap: 18px;
    /* Text line box ends at 6166, the pills start at 6191. */
    margin-block-start: 25px;
  }

  .contact-cta__cta {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    block-size: 37px;
    /* Figma draws 195px and 159px. Measured in Poppins Medium 17 the two
       labels set at 168.25px and 132.84px, so both pills are their label plus
       13.25px of air on each side and one padding rule reproduces both widths
       to within a third of a pixel. */
    padding-inline: 13.25px;
    border-radius: var(--radius-2xl);
    color: var(--color-on-dark);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    line-height: var(--leading-button);
    white-space: nowrap;
    text-decoration: none;
    isolation: isolate;
  }

  .contact-cta__cta::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background-image: var(--gradient-brand);
    /* The shadow is on the same node as the 70% fill in Figma, so it is faded
       with it rather than drawn at full strength. */
    box-shadow: var(--shadow-card);
    opacity: 0.7;
    transition: opacity var(--duration-fast) var(--ease-out);
  }

  .contact-cta__cta:hover::before,
  .contact-cta__cta:focus-visible::before {
    opacity: 1;
  }

  /* ------------------------------------------------------------------
     Portraits. Both are transparent cut-outs whose bottom edge is exactly the
     banner's bottom edge (6306), so they are anchored to it and overhang its
     TOP by 201px and 213px — the overlap the design is built around.
     ------------------------------------------------------------------ */

  .contact-cta__portrait {
    position: absolute;
    inset-block-end: 0;
    max-inline-size: none;
    block-size: auto;
    object-fit: cover;
    pointer-events: none;
  }

  .contact-cta__portrait-back {
    /* tobias-poperl-hochauflösend 1 (190:242), 726..1073. Anchored to the
       banner's RIGHT edge (1326 - 1073 = 253) rather than its left, because
       above 1440 the banner keeps widening while the pair must stay at its
       end. The px terms freeze both portraits at design size and design
       spacing past 1440, so their overlap survives; below 1440 the percentage
       wins and the whole group scales with the banner. The box aspect matches
       the source, so cover is a straight fit. */
    inset-inline-end: min(20.721%, 253px);   /* 253 / 1221 */
    inline-size: min(28.420%, 347px);        /* 347 / 1221 */
    aspect-ratio: 347 / 487;
  }

  .contact-cta__portrait-front {
    /* IMG_0696 feed 1 (190:243), 811..1417 — its box overhangs the banner's
       right edge by 91px, which is why the inset is negative. Figma scales the
       fill to 152.09% height and offsets it -16.43%, i.e. cover with the crop
       taken 31.55% down the source instead of centred:
       82 / (758.9 - 499) = 0.3155. */
    inset-inline-end: max(-7.453%, -91px);   /* -91 / 1221 */
    inline-size: min(49.632%, 606px);        /* 606 / 1221 */
    aspect-ratio: 606 / 499;
    object-position: 50% 31.55%;
  }

  /* ------------------------------------------------------------------
     Below 1440 there is no comp. Decisions made here, listed in the report:

       - everything above scales as a fraction of the banner, so the whole
         composition (text column, portrait overlap, bleed) holds down to
         roughly 900px without a single override;
       - under 900px the copy can no longer live in 41% of the banner while
         two people occupy the rest, so the portraits are dropped and the text
         takes the full width. A mobile comp is needed to do better than that;
       - the empty grey below the banner is the missing footer's space. It is
         reproduced at 326px on desktop and cut to 120px on small screens,
         where a third of a phone screen of nothing reads as a broken page.
     ------------------------------------------------------------------ */

  @media (width < 900px) {
    .contact-cta__portrait {
      display: none;
    }

    .contact-cta__banner-body {
      max-inline-size: none;
    }
  }

  @media (width < 768px) {
    .contact-cta {
      padding-block: 48px 120px;
    }

    .contact-cta__band {
      /* Keeps the banner straddling the edge the same way: 143px of the band
         overlaps the banner, the rest is the space below it. */
      block-size: 263px;
    }

    .contact-cta__banner {
      margin-block-start: 40px;
      padding-block: 40px;
    }

    .contact-cta__cta {
      /* A pill that has to wrap its label is worse than one that grows. */
      block-size: auto;
      padding-block: 10px;
      white-space: normal;
      text-align: center;
    }
  }
}

@layer sections {
  /* ------------------------------------------------------------------
     variant: plain — the interior-page version of this banner.

     Same block, no portraits, and the design indents the heading and the
     banner's own content slightly more than on the Startseite. Measured off
     the Agentur frame (213:32): heading x = 133 against the banner's 107,
     and the banner's copy starts 93 inside it rather than 74.
     ------------------------------------------------------------------ */

  .contact-cta[data-variant="plain"] .contact-cta__title {
    margin-inline-start: 26px;
    /* Figma allocates the same 117px text box on both pages, but this page's
       title is one line where the Startseite's is two. Without reserving the
       drawn height the banner rides up 56px and the section ends short. */
    min-block-size: 112px;
  }

  .contact-cta[data-variant="plain"] .contact-cta__banner-body {
    /* 93 - 74 = 19 more than the default inset. */
    margin-inline-start: 19px;
    /* Without the portraits the copy is free to use the full banner. */
    max-inline-size: none;
  }
}

@layer sections {
  /* ------------------------------------------------------------------
     variant: solo — one portrait instead of two, and a shallower grey band.

     Measured off the Geld-Zurück-Garantie frame (217:25): banner x = 122
     w = 1208, single portrait at x = 841 (so 142 in from the banner's right
     edge against the Startseite's 253), grey band 276 tall at y = 2790
     against the Startseite's 469.
     ------------------------------------------------------------------ */

  .contact-cta[data-variant="solo"] .contact-cta__title {
    /* h2 at 2431 against a section opening at 2360. */
    min-block-size: 112px;
  }

  .contact-cta[data-variant="solo"] .contact-cta__banner {
    /* Title closes at 2543, banner opens at 2646. */
    margin-block-start: 103px;
  }

  .contact-cta[data-variant="solo"] .contact-cta__portrait-back {
    inset-inline-end: min(11.755%, 142px);   /* 142 / 1208 */
  }

  .contact-cta[data-variant="solo"] .contact-cta__band {
    /* 2790 from a section opening at 2360, and 276 tall rather than 469. */
    inset-block-start: 430px;
    block-size: 276px;
  }
}

@layer sections {
  /* ------------------------------------------------------------------
     variant: feature — the front portrait only, on a wider banner.

     Measured off the Blog frame (218:358): banner x = 130 w = 1223, the
     single portrait at x = 700 (47 in from the banner's right edge against
     the Startseite's -91, where it overhangs), heading at 136 / 2303.
     ------------------------------------------------------------------ */

  .contact-cta[data-variant="feature"] .contact-cta__title {
    margin-inline-start: 6px;
    min-block-size: 112px;
  }

  .contact-cta[data-variant="feature"] .contact-cta__banner {
    /* Title closes at 2415, banner opens at 2471. */
    margin-block-start: 56px;
  }

  .contact-cta[data-variant="feature"] .contact-cta__portrait-front {
    inset-inline-end: min(3.843%, 47px);   /* 47 / 1223 */
  }

  .contact-cta[data-variant="feature"] .contact-cta__band {
    inset-block-start: 390px;   /* 2615 from a section opening at 2225 */
  }
}
