/* Secondary links (geo attribution, billing help, more options) sit on a
   single row below the CTA at normal widths and wrap to two rows on narrow
   carousels.  Kept smaller than the surrounding form text so they
   don't compete with the CTA. */
.checkout-secondary-actions {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  /* Horizontal spacing is handled by the `.actions-separator` middots,
     so only carry a row gap for when the line wraps on narrow widths. */
  gap: 6px 8px;
}

.actions-separator {
  color: #888;
  font-size: 12px;
  user-select: none;
}

/* Struck original price next to a larger discounted price. Applied
   server-side via window.__DISCOUNT__ — the client mutates the same
   spans on currency change and on typed-input apply. */
.price-original {
  font-size: 0.6em;
  color: #888;
  margin-right: 6px;
  text-decoration: line-through;
  text-decoration-thickness: 2px;
  text-decoration-skip-ink: none;
}

/* The sliding-scale tier amount wraps an optional .price-original sibling
   plus the discounted text. inline-flex with align-items: center makes both
   the smaller strikethrough span and the larger discounted text behave as
   flex items, which the parent `align-items: center` flex container then
   centers vertically — same mechanism that aligns the /month interval label. */
/* Display text (amounts, totals, headings) is Heebo; body text stays Inter. */
.sliding-scale-card-amount {
  display: inline-flex;
  align-items: center;
  font-family: 'Heebo', sans-serif;
}

/* Region-specific greeting rendered below the subscribe CTA when the
   visitor's IP matches a configured entry in PROMOTIONS_GEO_BLURBS
   (e.g. the Kamaʻāina blurb for US-HI). Server-side rendered with
   pre-parsed bold marks. */
.geo-blurb {
  margin-top: 12px;
  text-align: center;
  color: #1a5035;
  font-size: 14px;
  line-height: 1.45;
  max-width: 640px;
}

.geo-blurb-line {
  margin: 0;
}

.geo-blurb-line + .geo-blurb-line {
  margin-top: 4px;
}

.geo-blurb-line strong {
  font-weight: 600;
}

/* "Draft" badge rendered above the blurb when the underlying Sanity
   document is from the drafts pool. Only ever surfaces in dev/staging
   (production doesn't stream drafts), so the styling is loud on
   purpose — makes it obvious to internal reviewers that the message
   isn't yet live. */
.geo-blurb-draft-badge {
  display: inline-block;
  margin-bottom: 8px;
  padding: 2px 8px;
  border-radius: 4px;
  background-color: #fef3c7;
  color: #92400e;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.checkout-loading::after {
  content: '';
  /* Lay out the spinner on top of its closest `position: relative` parent. */
  position: absolute;
  width: 16px;
  height: 16px;
  border: 4px solid transparent;
  border-radius: 50%;
  border-top-color: #ffffff;
  animation: rotating 1s ease infinite;
}

@keyframes rotating {
  from {
    transform: rotate(0turn);
  }

  to {
    transform: rotate(1turn);
  }
}

.error-message {
  background-color: #fee;
  border: 1px solid #fcc;
  color: #c33;
  padding: 10px;
  border-radius: 4px;
  margin-bottom: 20px;
}

.checkout-checkbox {
  transition: all 0.3s ease;
}

.stripe-badge {
  height: 24px;
  width: auto;
  vertical-align: middle;
}

.billing-help-link {
  font-size: 12px;
  font-family: 'Inter', sans-serif;
  color: #2c8658;
  text-decoration: underline;
  cursor: pointer;
  text-align: center;
}

/* ---------- Sliding-scale amount selector ---------- */

.sliding-scale-cards {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  gap: 12px;
  min-width: 0;
  /* `overflow: auto hidden` gives us horizontal scroll (for the card
     carousel) with explicit vertical clipping.  Without the explicit
     hidden, `overflow-x: auto` is promoted to `overflow: auto auto`
     per the spec — and if an ancestor constrains this element's
     height, the implicit vertical overflow becomes a real scrollbar
     the user can drag around. */
  overflow: auto hidden;
  /* Contain horizontal overscroll within the card carousel so a
     swipe past the leftmost or rightmost card doesn't rubber-band
     and reveal empty space outside the carousel's content. */
  overscroll-behavior-x: contain;
  /* Breathing room for the card ribbon's top overhang and the
     bonus badge's downward growth.  The badge font's `clamp(8px,
     6cqi, 11px)` keeps English on a single line across the
     common embed widths, but very narrow phones or longer
     localized strings (Japanese) can still wrap to two lines —
     budget enough bottom padding for that worst case (~24px
     below the card) plus the selected-card focus outline (4px). */
  padding: 16px 2px 28px;
  margin: 0;
  list-style: none;
  scroll-snap-type: x mandatory;
  /* Match the container's horizontal padding so the first card's
     start-aligned snap position resolves to `scrollLeft: 0`.
     Without this, the snap rests at `scrollLeft = padding-left`
     and the "scroll back" arrow's `scrollLeft <= 1` disable check
     never trips at the leftmost position (the rightmost works
     because the last card's snap is unreachable, so it rests at
     the true max `scrollWidth - clientWidth`). */
  scroll-padding-inline: 2px;
  scrollbar-width: none;
  scroll-behavior: smooth;
  /* Progressive enhancement: Chrome/Edge 129+ honor `scroll-start-inline`
     and position the scroller at the middle of its content on load, which
     — because the default-selected tier is configured to be the middle
     preset — shows the default roughly centered in 3-up layouts and in
     the left column of 2-up / 1-up layouts without any JS.  Browsers
     that don't support this fall through to `__positionAmountCards__`
     (partials/amountCardsInitialScroll.ejs). */
  scroll-start-inline: center;
  /* Tell the browser to auto-generate a pagination marker group after
     the scroll container. */
  scroll-marker-group: after;
}
.sliding-scale-cards::-webkit-scrollbar {
  display: none;
}

/* Browser-generated pagination dots (Chrome 135+).  Safari/Firefox
   users simply see no dots; the fallback arrow buttons (wired up in
   `src/client/amountCarousel.ts`) still let them navigate the carousel.  We
   deliberately skip `::scroll-button` here: those pseudos are rendered
   *inside* the scroll container, which would overlap the cards — the
   flex-wrapper-with-sibling-arrows pattern below gives a nicer layout
   in every browser. */
.sliding-scale-cards::scroll-marker-group {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 8px;
}
.sliding-scale-card-item::scroll-marker {
  content: '';
  display: block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #d5e5dc;
  border: none;
  cursor: pointer;
  transition: background-color 120ms ease-in-out;
}
.sliding-scale-card-item::scroll-marker:target-current {
  background: #2c8658;
}

/* Interval toggle drives which card list is visible.  Wrapper is a
   flex row so the fallback prev/next arrows sit beside the scrolling
   card list rather than floating over it. */
.sliding-scale-scroll-wrapper {
  display: flex;
  /* Stretch so the inner cards list (the unmarked flex child)
     fills the wrapper's height — combined with the grid stack
     on `.sliding-scale-cards-stack`, this propagates the taller
     interval's height down into the cards themselves so monthly
     and yearly cards stay the same size on toggle.  Arrows opt
     out via their own `align-self: center`. */
  align-items: stretch;
  /* No `gap` here: a `cqi`-based gap on this element would resolve
     against the nearest *ancestor* query container (the carousel),
     not the wrapper itself.  Instead, the spacing between arrows
     and the cards list is set via margins on the arrow buttons
     (`.sliding-scale-fallback-arrow-prev` / `-next` below), which
     are children of this wrapper and therefore correctly query
     the wrapper's own width via this element's `container-type`. */
  position: relative;
  /* `container-type: inline-size` gives this element inline-size
     containment (so the 4 preset cards' intrinsic min-content doesn't
     bubble up and widen the ancestor `.express-card`) AND makes
     it a container-query root so the card count scales with the
     wrapper's width via `@container` rules below.  Named so rules
     targeting elements *inside* a card (which sits within the
     `.sliding-scale-card-item` container) can still query the
     wrapper's width rather than the card's. */
  container: sliding-scale / inline-size;
  min-width: 0;
  max-width: 100%;
}

/* Stack the month and year scroll-wrappers in the same grid cell so
   the cell sizes to whichever list is taller.  The inactive list is
   hidden with `visibility: hidden` instead of `display: none` so it
   still consumes layout — toggling intervals no longer reflows the
   form below.  Both wrappers retain their `display: flex` layout
   from the base rule above. */
.sliding-scale-cards-stack {
  display: grid;
  grid-template-columns: 1fr;
  min-width: 0;
}

.sliding-scale-cards-stack > .sliding-scale-scroll-wrapper {
  grid-column: 1;
  grid-row: 1;
}

/* Every stacked list starts hidden and the checked interval radio reveals its
   own.  Keyed on `data-interval-radio` rather than a radio id, so the stack
   does not care how many cadences are enabled.  Pure `:has()`, so switching
   works before any script loads. */
.sliding-scale-cards-stack > .sliding-scale-scroll-wrapper {
  visibility: hidden;
}

.amount-carousel-scope:has([data-interval-radio='month']:checked) .sliding-scale-scroll-wrapper-month,
.amount-carousel-scope:has([data-interval-radio='year']:checked) .sliding-scale-scroll-wrapper-year,
.amount-carousel-scope:has([data-interval-radio='one_time']:checked) .sliding-scale-scroll-wrapper-one_time {
  visibility: visible;
}

/* Pager buttons used in every browser.  Placed alongside the scroll
   container via the flex-wrapper above so they sit outside the card
   area rather than over it. */
.sliding-scale-fallback-arrow {
  flex: 0 0 auto;
  align-self: center;
  /* Arrows shrink with the wrapper's width so cards have room to
     breathe on narrow embeds (phones) — the wrapper carries the
     `container-type: inline-size` that `cqi` reads.  Minimum size
     is floored at 32px on phones so the buttons stay comfortably
     tappable (Apple's 44px guideline is the desktop ceiling). */
  width: clamp(32px, 9cqi, 44px);
  height: clamp(32px, 9cqi, 44px);
  border: 1px solid #d5e5dc;
  border-radius: 50%;
  background: white;
  color: #1b5035;
  font-size: clamp(16px, 6cqi, 24px);
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    background-color 120ms ease-in-out,
    border-color 120ms ease-in-out,
    opacity 120ms ease-in-out;
}
.sliding-scale-fallback-arrow:hover:not(:disabled) {
  background: #eef7f1;
  border-color: #2c8658;
}
.sliding-scale-fallback-arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Spacing between arrows and the cards list, set as logical margins
   on the arrow buttons rather than a `gap` on the wrapper.  Because
   the buttons are children of the wrapper (which carries
   `container-type: inline-size`), their `cqi` here resolves against
   the wrapper's own width — unlike a `gap` declared on the wrapper
   itself, which would resolve against the wrapper's nearest ancestor
   query container (the carousel) instead. */
.sliding-scale-fallback-arrow-prev {
  margin-inline-end: clamp(2px, 1.5cqi, 8px);
}
.sliding-scale-fallback-arrow-next {
  margin-inline-start: clamp(2px, 1.5cqi, 8px);
}

.sliding-scale-card-item {
  /* 3 cards visible by default; the container-query rules below keep
     3 across phone widths (paying for them with the pager arrows) and
     drop to 2 only on genuinely tiny embeds. */
  flex: 0 0 calc((100% - 24px) / 3);
  /* Align snap points with the container's start so the programmatic
     resting position lands on a snap position.  Using `center` here
     means programmatic scrolls that use `inline: 'nearest'` won't
     land on the snap point unless the card was already near center. */
  scroll-snap-align: start;
  list-style: none;
  /* Lets the bonus badge inside scale via cqi against the card's
     own width — at 2-up / 1-up breakpoints the card narrows and
     the badge's text + horizontal padding shrink so it stays
     within the card's bounds instead of overhanging into adjacent
     cards or being clipped at the carousel's edge. */
  container-type: inline-size;
}

/* Narrow wrappers get the peek treatment either way; how many cards fit
   depends on whether the pager arrows are there, which depends on the
   input, not the width.  A narrow embed on a desktop — or just a
   resized browser window — is still mouse-only, and with the scrollbar
   hidden and `::scroll-marker` not painting (it doesn't, in any browser
   tested) the arrows would be the only pointer affordance left.  So
   they only go away for a coarse primary pointer, where the swipe they
   duplicate actually exists, and that reclaimed width is what buys the
   third card. */
@container sliding-scale (max-width: 560px) {
  .sliding-scale-cards {
    --sliding-scale-gap: clamp(4px, 2cqi, 8px);
    --sliding-scale-peek: clamp(6px, 3cqi, 14px);
    gap: var(--sliding-scale-gap);
    /* Insetting each snap position by a gap + a peek both leaves the
       neighbor's edge showing and puts the middle card's centered
       resting position (`__positionAmountCards__`)
       exactly on the snap point of the card to its left — otherwise
       `scroll-snap-type: mandatory` yanks the default tier back. */
    scroll-padding-inline: calc(var(--sliding-scale-gap) + var(--sliding-scale-peek));
    /* Two badge lines: cards this narrow push the longer labels past
       the auto-fit's 8px floor (`fitAllBonusBadges`) and
       they wrap.  Under desktop's 28px because the selected-card focus
       outline needs `:focus-visible`, which touch never triggers. */
    padding-bottom: 24px;
  }

  /* Arrows present: 2 cards plus the 3 gaps and 2 peeks framing them.
     Three would leave ~74px each once the arrows take their ~74px back,
     which is narrower than this layout can carry. */
  .sliding-scale-card-item {
    flex-basis: calc((100% - 2 * var(--sliding-scale-peek) - 3 * var(--sliding-scale-gap)) / 2);
  }

  @media (pointer: coarse) {
    .sliding-scale-fallback-arrow {
      display: none;
    }

    /* 3 cards plus the 4 gaps and 2 peeks framing them. */
    .sliding-scale-card-item {
      flex-basis: calc((100% - 2 * var(--sliding-scale-peek) - 4 * var(--sliding-scale-gap)) / 3);
    }
  }
}

/* Smallest phones.  Cards are ~86px here, narrow enough that the
   longest localized badges ("🌳 2 Bonusbäume / Jahr") bottom out at the
   auto-fit's 8px floor and wrap to three lines, which overruns the
   two-line reservation above. */
@container sliding-scale (max-width: 340px) {
  .sliding-scale-cards {
    padding-bottom: 32px;
  }
}

/* Below phone widths — sidebar-sized embeds — a third card would be
   too narrow to read, so drop to 2 and let them take the freed width.
   The peek and snap inset carry over from the rule above. */
@container sliding-scale (max-width: 270px) {
  .sliding-scale-card-item {
    flex-basis: calc((100% - 2 * var(--sliding-scale-peek) - 3 * var(--sliding-scale-gap)) / 2);
  }
}

.sliding-scale-card-label {
  display: block;
  cursor: pointer;
  /* Stretch the label to fill its `<li>`.  Flex `align-items: stretch`
     on `.sliding-scale-cards` makes all items the tallest item's
     height, but without this the label (and the .sliding-scale-card
     inside it) would only be tall enough for its own content — so
     badge-less cards would show a shorter visual box than badged
     ones.  `height: 100%` lets the box grow to match. */
  height: 100%;
}

.sliding-scale-card-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.sliding-scale-card {
  border: 1px solid #d5e5dc;
  border-radius: 12px;
  /* Vertical padding scales with viewport so cards breathe on desktop
     without looking lanky on phones; horizontal scales similarly but
     stays more modest to keep prices centered in narrow preset widths. */
  padding: clamp(20px, 4vw, 40px) clamp(14px, 2.5vw, 20px);
  background: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Cards stretch to the tallest in the row while the tree copy runs
     1-3 lines, so centering the stack lands every card's price at a
     different height.  The slack goes to the tree copy instead. */
  justify-content: flex-start;
  gap: 8px;
  position: relative;
  /* Grow to fill the label (which fills the `<li>`), so cards without
     bonus badges render the same visual height as cards with them. */
  height: 100%;
  box-sizing: border-box;
  transition:
    border-color 120ms ease-in-out,
    box-shadow 120ms ease-in-out,
    transform 120ms ease-in-out;
  text-align: center;
}

.sliding-scale-card-label:hover .sliding-scale-card {
  border-color: #2c8658;
}

.sliding-scale-card-input:checked + .sliding-scale-card {
  border-color: #2c8658;
  box-shadow: 0 0 0 2px #2c8658 inset;
}

.sliding-scale-card-input:focus-visible + .sliding-scale-card {
  outline: 2px solid #2c8658;
  outline-offset: 2px;
}

.sliding-scale-card-ribbon {
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  background: #2c8658;
  color: white;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 999px;
  letter-spacing: 0.02em;
  /* Keep the badge on a single line even when the card is narrow
     (e.g. the 2-up and 1-up container-query breakpoints).  The badge
     is already designed to overhang the card horizontally (centered
     via translateX(-50%) with top: -10px), so letting it bleed past
     the card edges is the intended behavior. */
  white-space: nowrap;
}

.sliding-scale-card-amount-row {
  display: flex;
  /* `center` (vs the earlier `baseline`) puts the smaller "/month"
     suffix at the vertical midpoint of the price digits instead of
     aligning it to the digit baseline, which looked bottom-heavy
     against the tall clamp-sized price. */
  align-items: center;
  justify-content: center;
  gap: 0;
  /* Long localized prices — e.g. pt_BR's "R$ 1,5 mil /ano" — can
     out-grow the card.  Wrap so the interval suffix moves to its
     own line under the price instead of overflowing the card to
     the left/right. */
  flex-wrap: wrap;
  row-gap: 2px;
}

/* Card-relative `cqi` (via `container-type: inline-size` on
   `.sliding-scale-card-item`) keeps the price legible without
   bleeding past the card's own bounds at any breakpoint.  The
   previous `vw` formula read from the host viewport, so on a wide
   browser with a narrow embedded iframe the font would peg at its
   max and overflow the card. */
.sliding-scale-card-amount {
  font-size: clamp(20px, 14cqi, 42px);
  font-weight: 700;
  color: #2c8658;
}

.sliding-scale-card-interval {
  font-size: clamp(12px, 4cqi, 16px);
  color: #4a6b5a;
}

.sliding-scale-card-equivalent {
  font-size: clamp(12px, 4cqi, 16px);
  color: #4a6b5a;
  line-height: 1.3;
  /* Takes the card's leftover height so the price row stays pinned to
     the top while this copy still sits centered in what is left. */
  margin-block: auto;
}

/* Phone-width tuning for the card's interior.  A card is ~95-110px wide
   at the 3-up layout, and every one of these values costs height at that
   width: the desktop side padding pushes the "/month" suffix onto its
   own row, and the 12px floors wrap the tree copy to a third line.  Each
   card stretches to the tallest, so one wrapped line makes the whole row
   taller than it is wide.  Trimming them lands the card near square
   without capping its height — `aspect-ratio` can't do that job here,
   since content min-size wins and the longer localized strings would
   simply overflow.

   Declared after the base rules rather than in the phone block further
   up: same specificity, so these have to come later to win. */
@container sliding-scale (max-width: 560px) {
  .sliding-scale-card {
    padding: clamp(10px, 4cqi, 40px) clamp(6px, 8cqi, 14px);
    gap: 6px;
  }

  .sliding-scale-card-interval,
  .sliding-scale-card-equivalent {
    font-size: clamp(11px, 4cqi, 16px);
  }

  .sliding-scale-card-equivalent {
    line-height: 1.2;
  }
}

/* Mirror of .sliding-scale-card-ribbon but anchored at the bottom
   edge so it reads as a sticker pinned to the card.  Absolute
   positioning keeps the card's main content (price, tree copy)
   centered the same way on every card — badged or not — so the
   default `[hidden] { display: none }` behavior is exactly what we
   want for the empty state.

   The badge is top-anchored (rather than `bottom: -10px`) so when a
   long localized label — e.g. Japanese "🌳 年間2本のボーナスツリー" —
   wraps to a second line, the extra height extends *downward* below
   the card.  Bottom-anchoring would have pushed the wrapped text
   up into the card's content area instead.  `max-width: 100%` plus
   `white-space: normal` lets the text wrap inside the card's
   horizontal bounds rather than overflowing into the carousel
   gutter.

   Centered by `inset-inline: 0` + `margin-inline: auto` rather than
   `left: 50%` + a translate: with only `left` set, shrink-to-fit
   measures from the badge's left edge to the card's right edge, so a
   wrapping badge gets half the card's width and stacks into three
   lines.  Anchoring both edges gives it the card's full width. */
.sliding-scale-card-bonus-badge {
  position: absolute;
  top: 100%;
  margin-top: -4px;
  inset-inline: 0;
  width: fit-content;
  margin-inline: auto;
  max-width: 100%;
  box-sizing: border-box;
  /* Also the credits explainer's trigger, so the whole pill is the hit
     target.  The (i) it carries had to wrap to its own line inside the
     tree copy on a ~100px card, and its 32px hit target became 32px of
     the copy's height — enough to knock the copy off the center line
     the other cards' copy sits on. */
  appearance: none;
  border: none;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  /* Keeps the (i) centered against the label when it wraps. */
  align-items: center;
  gap: 3px;
  /* Font + horizontal padding scale with the parent card's width
     (via the `container-type: inline-size` on .sliding-scale-card-item)
     so the badge stays inside the card at every card count instead
     of overhanging into adjacent cards or getting clipped at the
     carousel edges on phones.  The block padding is what puts the pill
     over the 24px hit-target threshold. */
  padding: 5px 6px;
  background: #eef6f1;
  color: #2c8658;
  /* Reasonable no-JS fallback.  `fitAllBonusBadges` in
     amountCardText.ts overrides `font-size` (and `white-space`) at runtime
     to shrink each badge until it fits its own card on a single
     line — pure-CSS scaling can't compensate for per-language /
     per-platform glyph width differences, so the auto-fit is what
     actually makes the badge reliably single-line. */
  font-size: 10px;
  font-weight: 500;
  text-align: center;
  /* Fixed corner radius — `border-radius: 999px` produced
     extreme semicircular ends once the badge wrapped to two
     lines, which made the pill read as a vertical capsule with
     the curves bigger than the text. */
  border-radius: 10px;
  line-height: 1.2;
  white-space: normal;
  /* Transparent outline reserves a transitionable channel so the
     selected-state outline below animates in/out without a layout
     shift, matching the BEST VALUE badge's pattern. */
  outline: 1px solid transparent;
  transition: outline-color 120ms ease-in-out;
}

/* `display: flex` above outranks the UA stylesheet's
   `[hidden] { display: none }` at the same specificity, so without this
   the pill renders on every card regardless of the template's `hidden`
   attribute. */
.sliding-scale-card-bonus-badge[hidden] {
  display: none;
}

.sliding-scale-card-input:checked + .sliding-scale-card .sliding-scale-card-bonus-badge {
  outline-color: #2c8658;
}

.sliding-scale-card-bonus-badge:focus-visible {
  outline: 2px solid #2c8658;
  outline-offset: 1px;
}

/* Names the pill for assistive tech without an `aria-label`, which
   would have replaced the bonus copy it wraps rather than adding to
   it.  Standard sr-only clip pattern. */
.sliding-scale-card-bonus-badge-hint {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- TREE-336: credits-explainer popover -------------------- */

/* Sized against the badge copy it sits beside rather than as its own
   hit target — the pill is the target now, and it clears the 24px the
   accessibility audits look for across its whole width.  Every pixel
   here comes off the copy's width, which the auto-fit pays for in font
   size on a ~100px card. */
.sliding-scale-card-info-icon {
  display: inline-block;
  width: 14px;
  height: 14px;
  flex: none;
  opacity: 0.75;
  transition: opacity 120ms ease;
}

.sliding-scale-card-bonus-badge:hover .sliding-scale-card-info-icon,
.sliding-scale-card-bonus-badge:focus-visible .sliding-scale-card-info-icon {
  opacity: 1;
}

/* Until a card is selected its (i) is dimmed to signal that the
   explainer isn't the primary action there.  The tap itself picks the
   tier instead of opening the popover — `setupCreditsPopover` does
   that part, since the pill sits outside the card's box and so can't
   let a tap fall through to the surrounding label. */
.sliding-scale-card-input:not(:checked) + .sliding-scale-card .sliding-scale-card-info-icon {
  opacity: 0.35;
}

/* The popover element.  Visual styling only — positioning is
   handled by CSS Anchor Positioning in modern browsers (see the
   `@supports` block below), with a graceful fallback to the
   default `popover="auto"` rendering (top-layer, centered in
   viewport) for browsers that don't yet support it.
   `setupCreditsPopover()` only writes an inline `max-width` to
   cap by the device screen width — useful when the host page
   embeds the iframe wider than the device. */
.sliding-scale-credits-popover {
  max-width: min(340px, 92vw);
  padding: 16px 18px;
  border: 1px solid #d5e5dc;
  border-radius: 10px;
  background: white;
  color: #1b5035;
  font-family: 'Inter', sans-serif;
  box-shadow:
    0 4px 16px rgba(58, 68, 69, 0.16),
    0 2px 4px rgba(58, 68, 69, 0.08);
}

/* CSS Anchor Positioning (Chrome 125+ / Safari 26+): the
   browser uses the `popovertarget` invoker as the implicit
   anchor and places the popover directly below it.  If that
   would overflow the viewport, position-try-fallbacks shifts
   to the alternates (flipping vertically, then horizontally). */
@supports (position-area: bottom) {
  .sliding-scale-credits-popover {
    position-area: bottom;
    position-try-fallbacks: flip-block, flip-inline;
    margin-block-start: 12px;
  }
}

/* Backdrop pseudo-element rendered behind the popover while
   it's in the top layer.  A subtle blur draws the eye to the
   popover content without making the checkout feel modal —
   no color tint, since the popover is informational, not a
   confirmation prompt. */
.sliding-scale-credits-popover::backdrop {
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.sliding-scale-credits-popover-title {
  margin: 0 0 6px;
  font-size: 14px;
  font-weight: 600;
}
.sliding-scale-credits-popover-body {
  margin: 0 0 10px;
  font-size: 13px;
  line-height: 1.45;
  color: #4a6b5a;
}

/* Math block — accent background, tabular nums for clean digit
   alignment.  The fraction is an inline-block stack of two
   centered lines with a CSS border between them; result line
   sits below. */
.sliding-scale-credits-popover-math {
  margin: 0;
  padding: 10px 12px;
  background: #eef6f1;
  border-radius: 6px;
  font-size: 12.5px;
  line-height: 1.4;
  color: #1b5035;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.sliding-scale-credits-popover-math-fraction {
  display: inline-block;
  text-align: center;
}
/* Math row: fraction on the left, "× 12 months" multiplier on
   the right, vertically aligned to the divider line (the
   geometric middle of the fraction).  Wraps at narrow popover
   widths so the multiplier drops below the fraction rather than
   overflowing horizontally. */
.sliding-scale-credits-popover-math-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}
.sliding-scale-credits-popover-math-multiplier {
  white-space: nowrap;
  font-size: 12.5px;
}
.sliding-scale-credits-popover-math-numerator {
  padding: 0 8px 3px;
  border-bottom: 1px solid currentColor;
  white-space: nowrap;
}
.sliding-scale-credits-popover-math-denominator {
  padding: 3px 8px 0;
  white-space: nowrap;
}
.sliding-scale-credits-popover-math-result {
  display: block;
  margin-top: 6px;
  font-weight: 600;
}

/* Carry-over line.  Italic + smaller + muted to read as a
   footnote-style trailing remark below the math block. */
.sliding-scale-credits-popover-carryover {
  margin: 6px 0 0;
  font-size: 11.5px;
  color: #4a6b5a;
  font-style: italic;
  text-align: center;
}
