/**
 * @file
 * Sticky CTA component styles.
 *
 * Measured from the designer's export, tmp/sticky-ctas.png, at 2x — the same
 * scale as the form block's export. The panel measures 768x236 in a frame with
 * 48px of transparent margin on all four sides for the shadow, so:
 *
 *   panel            384 x 118
 *   corner radius    16       (measured 15; 16 matches the form panel and pill)
 *   padding          16
 *   copy             18px / 500 / #cf0000
 *
 * The panel sits flush to the bottom of the viewport and is rounded on its top
 * two corners only. The export is a standalone component frame with even margin
 * on all four sides, so it does not show that placement — it came from the
 * designer separately. The bottom corners and the shadow beneath them are off
 * screen in any case.
 *   copy -> buttons  12
 *   button height    52       (18px at line-height 1.5, so 12px padding-block)
 *   button gap       16
 *   shadow           spreads ~20px past every edge, evenly, peak alpha ~0.067
 *
 * Two places where this file deliberately departs from the export, both for
 * consistency with buttons already on the page:
 *
 * - Button corner radius measures ~2px. This uses the shared 4px. Two radii on
 *   one page reads as a bug, and 2px against 4px is not a difference anyone
 *   asked for.
 * - Button padding-inline measures 22px on the filled button and 16px on the
 *   outlined one. That is hand-sizing, not a spec, so both use the shared 16px.
 *   The filled button comes out ~13px narrower than the export and the row,
 *   being centred, simply reads slightly narrower.
 *
 * Ink measures #0c0c0c and this uses --ln-color-ink (#1c1c1c), which is what
 * every other button on the site uses and is indistinguishable at this size.
 */

.ln-sticky-cta {
  /**
   * Panel fill.
   *
   * The export has the panel at 80% white, so this is translucent as designed.
   * Worth knowing what that costs, because the panel floats over whatever
   * happens to be beneath it:
   *
   *   #cf0000 on #ffffff                        5.75:1  passes AA
   *   #cf0000 on 80% white over a dark photo    3.95:1  fails AA
   *
   * The copy is 18px, below WCAG's large-text threshold of 18.66px, so 4.5:1
   * applies rather than 3:1 whatever its weight. Over this page's own
   * backgrounds — white sections and the #ebebeb grey band — 80% white resolves
   * to about #f8f8f8 and the difference is invisible. It only bites over the
   * form block's background photograph.
   *
   * The blur below softens what is behind the panel but does not lighten it, so
   * those numbers are unchanged by it. Set the alpha to 1 to make the panel
   * opaque; nothing else needs to change.
   */
  --ln-sticky-cta-bg: rgba(255, 255, 255, 0.8);

  /**
   * Backdrop blur, from the designer's Figma output.
   *
   * Only does anything because the fill above is translucent — over an opaque
   * background there is nothing showing through to blur.
   */
  --ln-sticky-cta-blur: 30px;
  --ln-sticky-cta-fg: var(--ln-color-red, #cf0000);
  --ln-sticky-cta-radius: 16px;
  --ln-sticky-cta-padding: 16px;
  --ln-sticky-cta-max-inline-size: 384px;

  /* Copy row. 1.3 rather than the inherited leading: the line is a headline. */
  --ln-sticky-cta-copy-size: 18px;
  --ln-sticky-cta-copy-weight: 500;
  --ln-sticky-cta-copy-leading: 1.3;
  --ln-sticky-cta-copy-gap: 12px;

  --ln-sticky-cta-actions-gap: 16px;
  --ln-sticky-cta-button-padding-block: 12px;

  /**
   * Shadow.
   *
   * Centred, with no offset: the export's alpha immediately outside the panel is
   * 17/255 at the top, 17 at the right and 16 at the bottom, which is even
   * enough to read as no y-offset. A blurred edge shows half its source alpha,
   * and reaches zero about half a blur-radius out, so ~20px of spread and ~0.067
   * at the edge give a 40px blur at 0.15.
   *
   * Outer box-shadow is clipped to outside the border box, so it does not darken
   * the translucent fill.
   */
  --ln-sticky-cta-shadow: 0 0 40px rgba(0, 0, 0, 0.15);

  /**
   * Distance from the right edge of the viewport on desktop.
   *
   * There is no matching block inset: the panel is flush to the bottom, which is
   * also why only the top two corners are rounded.
   */
  --ln-sticky-cta-inset-inline: 24px;

  /**
   * Above page content, below Drupal's dialogs (which start at 1260) and below
   * anything the theme puts on the sticky site header. The panel sits at the
   * bottom and the header at the top, so those two cannot meet in any case.
   */
  --ln-sticky-cta-z-index: 100;

  position: fixed;
  z-index: var(--ln-sticky-cta-z-index);
  inset-block-end: 0;
  inset-inline-end: var(--ln-sticky-cta-inset-inline);
  inline-size: fit-content;
  max-inline-size: min(
    var(--ln-sticky-cta-max-inline-size),
    calc(100vw - (2 * var(--ln-sticky-cta-inset-inline)))
  );

  /**
   * Hidden state.
   *
   * visibility, not opacity alone. A visibility:hidden element is removed from
   * the tab order and from the accessibility tree, so a keyboard user cannot tab
   * into two invisible buttons before the panel has appeared — which is exactly
   * what an opacity-only hide would allow.
   *
   * display:none would also be inert, but it cannot be transitioned without
   * @starting-style, and it would make offsetHeight zero — which sticky-cta.js
   * reads before the panel is ever shown, to publish the height below.
   * visibility is discretely animatable and defers its switch to the end of the
   * transition, so it fades both ways.
   */
  visibility: hidden;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition:
    opacity 0.25s ease-out,
    transform 0.25s ease-out,
    visibility 0.25s;
}

.ln-sticky-cta.is-visible {
  visibility: visible;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.ln-sticky-cta__panel {
  display: flex;
  box-sizing: border-box;
  flex-direction: column;
  align-items: center;
  gap: var(--ln-sticky-cta-copy-gap);
  padding: var(--ln-sticky-cta-padding);
  /* Top corners only — the panel is flush to the bottom of the viewport, so the
     bottom two are off screen and rounding them would cut a sliver out of the
     fill along the bottom edge. */
  border-radius: var(--ln-sticky-cta-radius) var(--ln-sticky-cta-radius) 0 0;
  background-color: var(--ln-sticky-cta-bg);
  /* -webkit- first: Safari only dropped the prefix in 18, and iOS versions
     before that are still a meaningful share of the traffic this panel targets. */
  -webkit-backdrop-filter: blur(var(--ln-sticky-cta-blur));
  backdrop-filter: blur(var(--ln-sticky-cta-blur));
  box-shadow: var(--ln-sticky-cta-shadow);
}

/**
 * Where the blur cannot happen, lean on opacity instead.
 *
 * An unsupported backdrop-filter is simply ignored, which would leave 80% white
 * with nothing behind it resolved — the worst of both, and the case where the
 * contrast figures above actually bite. Nearly opaque is the safer failure.
 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ln-sticky-cta__panel {
    background-color: rgba(255, 255, 255, 0.95);
  }
}

/**
 * The copy.
 *
 * margin is zeroed explicitly. Cohesion sets margins, line-height (1.8) and
 * font-weight (300) on bare p elements, and a rule on the element beats an
 * inherited value from any ancestor however specific — so every one of those has
 * to be restated here rather than set on the panel and left to inherit. This is
 * the seventh component to need that; see the note in css/editor-styles.css.
 */
/* Class doubled to (0,2,0). This is a <p>, so the container-inherit rule in
   css/editor-styles.css matches it at (0,1,0) — undoubled, the panel's centred
   copy would inherit the page's left alignment instead. */
.ln-sticky-cta__copy.ln-sticky-cta__copy {
  margin: 0;
  color: var(--ln-sticky-cta-fg);
  font-family: var(--ln-font-sans, Outfit, sans-serif);
  font-size: var(--ln-sticky-cta-copy-size);
  font-weight: var(--ln-sticky-cta-copy-weight);
  line-height: var(--ln-sticky-cta-copy-leading);
  text-align: center;
  text-wrap: balance;
}

.ln-sticky-cta__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  gap: var(--ln-sticky-cta-actions-gap);
}

/**
 * Button overrides, scoped to the panel.
 *
 * Both are (0,2,0), so they beat .ln-button and the 62rem min-width rule inside
 * button.css whichever file the browser parses first.
 *
 * The shared button is 47px tall (10px padding-block); the export's is 52px.
 * And --ln-cta-min-width's 224px would put the pair at 464px inside a 384px
 * panel, so it is dropped here — these buttons size to their labels.
 */
.ln-sticky-cta .ln-button {
  --ln-button-min-width: 0;

  padding-block: var(--ln-sticky-cta-button-padding-block);
  white-space: nowrap;
}

/**
 * Phone: the same panel, widened to the page gutter.
 *
 * Measured from the designer's 401px comp, which corrected two guesses made
 * before it existed:
 *
 * - It is *not* full-bleed. The panel's shadow shows on both sides at 7.5-22 and
 *   379.5-394.5, straddling edges at roughly 15 and 386 — so it is inset by the
 *   page's own 16px gutter, and the top corners stay rounded because there is
 *   margin for them to curve into after all.
 * - The buttons keep their labels' widths and centre, rather than splitting the
 *   row in half. Measured 154px and 118px against a row centre of 200.75 in a
 *   401px frame — the same widths as desktop, so the pair simply travels down
 *   unchanged.
 *
 * What does change is the panel's width: 384px would leave only 8px a side here,
 * so it stretches to the gutter and the button row centres in the space.
 *
 * env(safe-area-inset-bottom) keeps the buttons clear of the home indicator on
 * a notched iPhone, where the bottom of the viewport is not the bottom of the
 * usable screen. It resolves to 0 everywhere else.
 */
@media (max-width: 47.99rem) {
  .ln-sticky-cta {
    /* 8px each side. The comp measures 16, but 8 is what was asked for on a real
       device. inset-block-end is already 0 on the base rule. */
    --ln-sticky-cta-inset-inline: 8px;

    inset-inline: var(--ln-sticky-cta-inset-inline);
    inline-size: auto;

    /**
     * The cap is in viewport units, and that is the fix rather than a belt.
     *
     * With both insets set and inline-size: auto, the used width is whatever sits
     * between them — so this ought to be viewport minus 16px and nothing more was
     * needed. It rendered 539px against a 430px viewport, which is only possible
     * if the box is not being measured against the viewport at all.
     *
     * position: fixed resolves against the initial containing block *unless* an
     * ancestor has a transform, filter, backdrop-filter, perspective,
     * contain: paint or will-change naming one of those — any of which makes that
     * ancestor the containing block instead. Then the insets are relative to it,
     * and if it is wider than the screen, so is this. Something in the page's
     * Site Studio wrappers is doing that.
     *
     * vw rather than a percentage for the same reason: a percentage would resolve
     * against whatever that containing block turns out to be, which is exactly
     * the value in question. vw always means the screen.
     *
     * The insets still do the positioning, so it is worth finding the offending
     * ancestor — see the note below the media query.
     */
    max-inline-size: calc(100vw - (2 * var(--ln-sticky-cta-inset-inline)));
  }

  .ln-sticky-cta__panel {
    /**
     * Translucent and blurred here too, same as desktop.
     *
     * This used to be opaque #ffffff, on the grounds that page text scrolling
     * behind translucent white with nothing softening it reads as a rendering
     * fault on a bar this size. The blur is precisely that mitigation, so the
     * exception no longer has a reason and has been dropped.
     *
     * One thing to watch on a real handset: this is a 30px backdrop blur across
     * the full viewport width, recomputed on every scroll frame, and that is the
     * most expensive shape this effect can take. If it janks on a mid-range
     * Android, putting `background-color: #fff` back here is the fix — the
     * backdrop-filter then has nothing to composite and costs nothing.
     */
    padding-block-end: calc(var(--ln-sticky-cta-padding) + env(safe-area-inset-bottom, 0px));
  }

/**
 * If the panel is ever the wrong width again, this is the thing to check.
 *
 * Paste into the console on the page: it walks up from the panel and reports any
 * ancestor that has taken over as the containing block for fixed positioning.
 *
 *   let n = document.querySelector('.ln-sticky-cta').parentElement;
 *   while (n && n !== document.documentElement) {
 *     const s = getComputedStyle(n);
 *     if (s.transform !== 'none' || s.filter !== 'none' ||
 *         s.backdropFilter !== 'none' || s.perspective !== 'none' ||
 *         s.contain.includes('paint') || s.willChange !== 'auto') {
 *       console.log(n, { transform: s.transform, filter: s.filter,
 *         backdropFilter: s.backdropFilter, perspective: s.perspective,
 *         contain: s.contain, willChange: s.willChange });
 *     }
 *     n = n.parentElement;
 *   }
 *
 * Whatever it names is the element the insets are measuring from. The vw cap
 * above keeps the width correct regardless, but the horizontal *position* is
 * still relative to that ancestor, so if the panel also sits off-centre or the
 * gap either side is uneven, this is why.
 */
  /* nowrap only. The two buttons measure 154px and 118px with a 17px gap, which
     is 289px inside a 369px panel — they fit side by side at this width, and
     wrapping one under the other would be a worse use of the space than the
     designer's centred row. */
  .ln-sticky-cta__actions {
    flex-wrap: nowrap;
  }
}

/**
 * Below roughly 340px the two labels stop fitting side by side.
 *
 * 289px of buttons plus 32px of panel padding needs 321px of viewport, and the
 * smallest phone still in circulation is 320px. Rather than let the row overflow
 * the panel, the buttons stack and stretch — the only place in this component
 * where they do.
 */
@media (max-width: 21.25rem) {
  .ln-sticky-cta__actions {
    align-self: stretch;
    flex-direction: column;
  }

  .ln-sticky-cta .ln-button {
    inline-size: 100%;
  }
}

/**
 * Room at the end of the page for the bar to sit in.
 *
 * The panel never goes away once shown, so on a phone the bar would permanently
 * cover the bottom ~90px of the page — and at the very bottom of the scroll
 * there is nothing left to scroll, so the last rows of the footer would be
 * unreachable rather than merely obscured.
 *
 * sticky-cta.js measures the panel and publishes its height on the root element,
 * so this tracks a two-line copy or a translated label that wraps. The fallback
 * covers the frame before the script runs.
 *
 * :has() means the reserve exists only on pages that actually place the block,
 * and it is unconditional rather than tied to .is-visible: reserving the space
 * only once the panel appears would change the page height mid-scroll and jump
 * the reader.
 *
 * Desktop is deliberately not reserved. There the panel is inset in the
 * bottom-right corner, so it overlaps a corner of the footer rather than a full
 * strip, and the rest of the page stays reachable. Move this rule out of the
 * media query if that overlap turns out to matter.
 */
@media (max-width: 47.99rem) {
  body:has(.ln-sticky-cta) {
    padding-block-end: var(--ln-sticky-cta-height, 96px);
  }
}

/**
 * Hide Site Studio's own sticky advertise button.
 *
 * #sticky-btn is the "Advertise Btn on Master Template - Sticky bottom on
 * Mobile" band in cohesion_master_templates.master_template, so it is on every
 * page the master template renders. Two sticky CTAs at the bottom of one screen
 * is one too many, and this one wins because the block is per-page content while
 * the master template's is not.
 *
 * Scoped by attachment, not by selector. This stylesheet is the sticky CTA
 * component's own, and SDC only attaches a component's CSS when the component
 * actually renders — so the rule ships only on pages that place the block, and
 * every other page keeps its button. That is why there is no :has() here, unlike
 * the reserve above: that rule targets `body`, which exists everywhere, so it
 * needs the guard. This one targets an element that is only ever a problem when
 * this component is present.
 *
 * An id selector is (1,0,0), which clears anything Site Studio can put on it —
 * its own styling comes through generated .coh-ce-* classes. No !important
 * needed, and none wanted: the intent is to be overridable by a later, more
 * specific rule if some page ever wants both.
 *
 * Worth knowing: the panel is hidden until the hero scrolls out of view, so
 * between page load and that point neither CTA is on screen. On this page the
 * hero carries the same two calls to action, so nothing is actually lost — but a
 * page whose hero does not would have a gap. Tying this to .is-visible instead
 * would fill it, at the cost of the two buttons visibly swapping mid-scroll,
 * which reads worse than a brief absence.
 *
 * Temporary by design: the button is expected to come out of the master template
 * once the rebuild is finished, at which point this rule can go with it.
 */
#sticky-btn {
  display: none;
}

/**
 * Layout Builder editing UI.
 *
 * Un-pin the panel so it renders inline in its section. A fixed panel would
 * float over the edit screen, covering whichever section happens to be at the
 * bottom of the viewport along with its contextual links and Add-block button.
 *
 * Un-pinned and visible rather than hidden: a hidden block cannot be configured,
 * moved or removed, so hiding it would strand it on the page.
 */
.layout-builder .ln-sticky-cta {
  position: static;
  visibility: visible;
  opacity: 1;
  transform: none;
  pointer-events: auto;
  inline-size: fit-content;
  max-inline-size: var(--ln-sticky-cta-max-inline-size);
}

@media (prefers-reduced-motion: reduce) {
  .ln-sticky-cta {
    transition: none;
    transform: none;
  }
}
