/*
  BoundBio — intro-offer popup styles
  =======================================
  Pairs with design-system/intro-popup.js. Two halves:

  1. `.ip-*` — our own chrome (backdrop, dialog card, close button).
     Modelled on the entry gate's card (see any page's own .gate-card
     rules) — the closest existing "centered modal card" precedent in the
     design system — same 400px cap, white fill, 1px line border, and the
     static size-pill / vault card surfaces for the color and spacing
     scale generally.

  2. Everything selector-prefixed `.ml-` or `#mlb2-45522806` — a complete
     override of MailerLite's own default look. Their stylesheet
     (assets.mlcdn.com/fonts.css, the black button, Open Sans, the grey
     card) is never loaded — see intro-popup.js, which strips that import
     from their snippet — so every one of these rules is filling in for
     CSS that would otherwise be entirely missing, not fighting a loaded
     stylesheet. The class names themselves are kept exactly as MailerLite
     generates them; only the declarations are ours. Do not rename them —
     webforms.min.js (their script, not ours) targets several by name.

  Depends on design-system/tokens.css for the custom properties referenced
  below — load that first.
*/

/* html.ip-lock, not body{overflow:hidden} directly — a class the way
   html.gate-active already works elsewhere, so this can never collide
   with some other script's own inline style.overflow. */
html.ip-lock, html.ip-lock body { overflow: hidden; }

.ip-backdrop {
  position: fixed;
  inset: 0;
  z-index: 150; /* below the gate's 200 (they should never coexist), above nav's 60 */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background: rgba(11, 27, 39, .5);
  opacity: 0;
  /* Belt-and-suspenders alongside the JS setting `hidden` on creation
     (design-system/intro-popup.js) — the popup lives in the DOM,
     invisible, for the whole pre-show wait, and again for ~220ms during
     its own fade-out in hide(). Without this, that invisible full-viewport
     `position:fixed` layer would silently swallow every click on the real
     page underneath it the entire time it's only opacity:0. */
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.ip-backdrop.is-open { opacity: 1; pointer-events: auto; }
.ip-backdrop[hidden] { display: none; }

.ip-modal {
  position: relative;
  width: 100%;
  max-width: 400px;
  max-height: calc(100svh - 2 * var(--space-5));
  /* hidden/auto, not a plain "hidden" shorthand — clips the ::before
     gradient below to the rounded corners on every edge while keeping
     vertical scroll alive for any content taller than max-height. A
     bare `overflow: hidden` here would silently clip instead of scroll. */
  overflow: hidden auto;
  background: var(--surface);
  border-radius: var(--radius-lg);
  /* 2026-09-04: was `border: 1px solid var(--line)` + a diffuse
     rgba(11,60,90,...) shadow — same navy-tinted family the gate card
     uses, but read as an outer blue glow/border around this specific
     card and was asked to go. Replaced with a neutral ink-based shadow
     (same offsets/blur/alpha, --ink's RGB instead of a blue one) so the
     card still floats off the dark backdrop with no color cast. Border
     dropped entirely — against the .ip-backdrop scrim there's nothing
     for a hairline to define that the shadow doesn't already do. */
  box-shadow: 0 24px 60px rgba(11, 27, 39, .18);
  padding: 34px 26px 26px;
  transform: translateY(14px) scale(.98);
  transition: transform var(--dur-slow) var(--ease-standard);
}
.ip-backdrop.is-open .ip-modal { transform: translateY(0) scale(1); }

/* Animated inner luminous gradient — lives INSIDE the card (z-index:0,
   behind every real child) rather than as anything outside it. Two
   radials from the site's existing blue tokens (copper is retired
   sitewide — design-system/tokens.css — so this uses --blue-deep for
   the second spot rather than reaching for it).
   Raised 2026-09-05 (max .16/.12 -> .28/.22, ~1.75x/1.8x) at Brian's
   request for more visual prominence. Doing that straight-up would
   break legibility, not just risk it: --ink-2 (the subhead) is only
   4.93:1 against PLAIN white with zero gradient at all — WCAG AA's
   4.5:1 floor for normal text was already this close before touching
   anything, and the ORIGINAL .16/.12 alpha had already pushed it
   under the line to ~4.1:1 (measured, not eyeballed — alpha-composite
   the gradient peak color over white, then WCAG-contrast that against
   #5F7382). Raising alpha further without protection would fail it
   outright — at .28/.22 the subhead measures ~3.5-3.8:1 with nothing
   behind it. Fixed at the source with a protective backing (below),
   not by capping the alpha back down — see .ml-form-embedContent and
   .ip-fineprint. The headline (--ink, large text, needs only 3:1) was
   never at risk either way — 12.6:1+ even unprotected at this alpha —
   so it's the only thing here still sitting directly on the raw
   gradient. */
.ip-modal::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 30% 20%, rgba(30, 143, 196, .28), rgba(30, 143, 196, .07) 40%, transparent 70%),
    radial-gradient(circle at 80% 85%, rgba(11, 109, 158, .22), transparent 60%);
  background-size: 200% 200%;
  animation: ip-luminous-drift 8s ease-in-out infinite;
  pointer-events: none;
  z-index: 0;
}
/* Lifts every real child (close button, the whole MailerLite embed)
   above the gradient layer — a direct-child selector is enough since
   normal stacking then carries everything nested inside #mlb2-45522806
   along with it; nothing deeper needs its own z-index. */
.ip-modal > * {
  position: relative;
  z-index: 1;
}
@keyframes ip-luminous-drift {
  0%   { background-position: 0% 0%, 100% 100%; }
  50%  { background-position: 100% 50%, 0% 50%; }
  100% { background-position: 0% 0%, 100% 100%; }
}

.ip-close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--line-soft);
  border: none;
  border-radius: 50%;
  color: var(--ink-2);
  transition: background var(--dur-base) var(--ease-standard), color var(--dur-base) var(--ease-standard);
}
.ip-close:hover { background: var(--line); color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .ip-backdrop, .ip-modal { transition: none; }
  .ip-modal::before { animation: none; }
}

/* ---- MailerLite embed, restyled (class names theirs, rules ours) ---- */
#mlb2-45522806 * { box-sizing: border-box; }

/* Frosted backing (2026-09-05) — same rgba(255,255,255,.78) +
   blur(10px) convention the rest of the site already uses for a
   surface over a dynamic background (CLAUDE.md "Surfaces"), reused
   here rather than inventing a one-off value. Structurally guarantees
   the subhead's contrast regardless of how vivid the gradient behind
   it gets, instead of relying on capping the gradient's own alpha —
   .78 clears 4.5:1 for --ink-2 against this gradient with margin
   (~4.6:1 measured) where the gradient alone, at any alpha above
   ~.08, cannot. The headline doesn't need this (12.6:1+ unprotected)
   but is included so the two lines read as one text block, not a
   patch appearing only under the second line. */
#mlb2-45522806 .ml-form-embedContent {
  text-align: center;
  margin-bottom: 20px;
  background: rgba(255, 255, 255, .78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: var(--radius-md);
  padding: 14px 16px;
}
#mlb2-45522806 .ml-form-embedContent h4 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  letter-spacing: var(--ls-display);
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 8px;
}
#mlb2-45522806 .ml-form-embedContent p {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-2);
  line-height: 1.5;
  margin: 0;
}

#mlb2-45522806 .ml-form-formContent { margin-bottom: 12px; }
#mlb2-45522806 .ml-form-fieldRow { margin: 0; }
#mlb2-45522806 .form-control {
  width: 100%;
  font-family: var(--font-body);
  font-size: 16px; /* 16px+ so iOS Safari doesn't zoom the page on focus */
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 13px 15px;
}
#mlb2-45522806 .form-control:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

#mlb2-45522806 .ml-form-embedSubmit { margin-top: 10px; }
#mlb2-45522806 .ml-form-embedSubmit .primary {
  width: 100%;
  background: var(--ink);
  color: #fff;
  border: none;
  border-radius: var(--radius-pill);
  padding: 14px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  transition: background var(--dur-base) var(--ease-standard);
}
#mlb2-45522806 .ml-form-embedSubmit .primary:hover { background: var(--blue-deep); }

#mlb2-45522806 .ml-form-embedSubmit .loading {
  width: 100%;
  background: var(--line-soft);
  color: var(--ink-2);
  border: none;
  border-radius: var(--radius-pill);
  padding: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
#mlb2-45522806 .ml-form-embedSubmitLoad {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid var(--line);
  border-top-color: var(--ink-2);
  animation: ip-spin .7s linear infinite;
}
@keyframes ip-spin { to { transform: rotate(360deg); } }

#mlb2-45522806 .sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Backing added alongside the gradient increase (2026-09-05), same
   reasoning as .ml-form-embedContent above — but flagged, not fully
   solved: --ink-3 measures only 2.86:1 against PLAIN white with no
   gradient involved at all, already under WCAG AA's 4.5:1 floor for
   normal text before this popup ever gets a background. No backing
   opacity toward white can close that gap — 100% opaque white is
   still only 2.86:1. This backing keeps the gradient increase from
   making that pre-existing gap worse (without it, the raised alpha
   would drag this down further, toward ~2:1); it does not make the
   line pass. --ink-3's own contrast against white is a sitewide
   design-token question, out of scope for a popup-gradient change —
   flagged in the round's report rather than patched here unasked. */
.ip-fineprint {
  font-size: 11.5px;
  color: var(--ink-3);
  line-height: 1.55;
  text-align: center;
  margin: 12px 0 0;
  background: rgba(255, 255, 255, .78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
}

/* Same backing as .ml-form-embedContent, same reasoning — the
   success state's h4/p pair sits directly on the gradient too and was
   missed on the first pass through this file; caught checking every
   text block against the gradient rather than just the ones visible
   on first load. */
#mlb2-45522806 .ml-form-successBody {
  text-align: center;
  background: rgba(255, 255, 255, .78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: var(--radius-md);
  padding: 14px 16px;
}
#mlb2-45522806 .ml-form-successContent h4 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  color: var(--ink);
  margin: 0 0 8px;
}
#mlb2-45522806 .ml-form-successContent p {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-2);
  line-height: 1.5;
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  #mlb2-45522806 .ml-form-embedSubmitLoad { animation: none; }
}

/* ---- Unique code reveal (2026-09-08) --------------------------------
   The code itself is painted by a MOVING gradient (background-clip: text +
   an animated background-position), not a static one: the sweep is the
   "reveal" beat. Brand blues only — no per-compound tint here. Under
   prefers-reduced-motion the gradient still paints, it just doesn't move.
   Contrast: the lightest stop (#7FD3F6) is decorative sweep, the resting
   fill is --blue-deep on the .78 white backing, ≥4.5:1. */
.ip-code-wrap { text-align: center; }
.ip-code-chip {
  display: inline-flex; flex-direction: column; align-items: center; gap: 4px;
  margin: 6px 0 12px; padding: 12px 22px 10px;
  background: #fff; border: 1px solid var(--line); border-radius: 16px;
  cursor: pointer; font: inherit; color: inherit;
  transition: box-shadow var(--dur-base) var(--ease-standard), transform var(--dur-base) var(--ease-standard);
}
.ip-code-chip:hover, .ip-code-chip:focus-visible { box-shadow: 0 0 0 2px var(--blue); outline: none; }
.ip-code-chip:active { transform: scale(.985); }
.ip-code-chip.is-copied { box-shadow: 0 0 0 2px var(--ok); }
.ip-code-text {
  font-family: var(--font-display); font-weight: 600; font-size: 24px; letter-spacing: .06em;
  background-image: linear-gradient(100deg, var(--blue-deep) 0%, var(--blue) 30%, #7FD3F6 50%, var(--blue) 70%, var(--blue-deep) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  animation: ip-code-sweep 2.2s linear infinite;
}
@keyframes ip-code-sweep { from { background-position: 0% 50%; } to { background-position: 300% 50%; } }
.ip-code-copy {
  font-family: var(--font-body); font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
}
.ip-code-chip.is-copied .ip-code-copy { color: var(--ok); }
.ip-error { font-family: var(--font-body); font-size: 13px; color: var(--ink-2); margin: 8px 0 0; text-align: center; }
.ip-error[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .ip-code-text { animation: none; background-position: 50% 50%; }
}
