/* ==========================================================================
   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)
   ========================================================================== */


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



  /* ------------------------------------------------------------------
     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;
  }



  /* ------------------------------------------------------------------
     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;
  }



  /* ------------------------------------------------------------------
     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 */
  }

