/* ============================================================================
   jp-mobile-components.css — Mobile component layer v1 (Block 46.1)
   ----------------------------------------------------------------------------
   Token-consuming components that replace the Block-45-era !important wars
   in jp-mobile-polish.css. Every value here is a var(--jp-*) reference; no
   raw hex / px for branded properties.

   Loaded AFTER jp-design-tokens.css and jp-mobile.css, BEFORE jp-mobile-polish.css
   (which we keep loaded temporarily until parity is verified across all 41
   mobile twins in a future block).

   Specificity strategy:
     • Single-class selectors where possible.
     • Where we need to defeat jp-marketing-mobile-v2.css's 3-class rules
       (e.g., `body.jp-m .hero .jp-btn-primary { background:#fff !important }`),
       match its specificity exactly — no higher. This keeps the cascade
       predictable: tokens → mobile base → marketing v2 → THIS FILE → polish.

   Desktop is untouched: every rule below is inside @media (max-width: 760px).
   ========================================================================== */

@media (max-width: 760px) {

  /* ── Topbar: 3-slot symmetric app-bar ──────────────────────────────────
     Block 46a — logo bumped 1.75× (28px → 49px), topbar lifted to 72px
     to give the larger mark room to breathe. Uses !important to defeat
     stale rules in jp-marketing-mobile-v2.css. */
  .topbar,
  header.topbar,
  .jp-m-appbar {
    position: sticky;
    top: 0;
    z-index: var(--jp-z-topbar);
    background: var(--jp-glass) !important;
    backdrop-filter: var(--jp-blur-glass) !important;
    -webkit-backdrop-filter: var(--jp-blur-glass) !important;
    border-bottom: 1px solid var(--jp-navy-08) !important;
    box-shadow: var(--jp-shadow-topbar) !important;
    padding-top: var(--jp-sa-top);
  }

  .topbar .topbar-inner,
  header.topbar .topbar-inner,
  .jp-m-appbar-inner {
    min-height: 72px !important;        /* Bumped from 56px to fit 1.75× logo */
    padding: var(--jp-sp-2) var(--jp-sp-4) !important;
    display: flex !important;
    align-items: center !important;
    gap: var(--jp-sp-2) !important;
    position: relative;
  }

  /* LEFT spacer — invisible 42px balance for the right hamburger */
  .topbar-spacer {
    flex: 0 0 42px !important;
    width: 42px !important;
    height: 42px !important;
    display: block !important;
  }

  /* CENTER logo — flex:1, centered, 49px image (28 × 1.75) */
  .topbar-logo,
  .jp-m-appbar-logo,
  header.topbar .topbar-logo {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-decoration: none !important;
    color: var(--jp-navy) !important;
    min-height: 60px !important;
    height: 60px !important;
    padding: 0 !important;
    border-radius: var(--jp-r-md) !important;
    flex: 1 1 auto !important;
    transition: background var(--jp-dur-1) var(--jp-ease-snap);
  }
  .topbar-logo:active,
  .jp-m-appbar-logo:active,
  header.topbar .topbar-logo:active {
    background: var(--jp-navy-04) !important;
  }
  .topbar-logo img,
  .jp-m-appbar-logo img,
  header.topbar .topbar-logo img,
  header.topbar .jp-m-appbar-logo img {
    height: 49px !important;            /* Block 46a: 28px × 1.75 = 49px */
    max-height: 49px !important;
    width: auto !important;
    max-width: 260px !important;
    display: block !important;
  }

  .jp-m-appbar-title,
  header.topbar .topbar-title {
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
    font-weight: var(--jp-fw-black);
    color: var(--jp-navy);
    font-size: var(--jp-fs-base);
    letter-spacing: var(--jp-ls-tight);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* RIGHT hamburger — navy-glass pill */
  .topbar-menu,
  .jp-m-appbar-menu {
    flex: 0 0 42px;
    width: 42px;
    height: 42px;
    min-height: 42px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--jp-navy-06);
    border: 1px solid var(--jp-navy-10);
    color: var(--jp-navy);
    border-radius: var(--jp-r-md);
    box-shadow: var(--jp-shadow-sm);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition:
      background var(--jp-dur-1) var(--jp-ease-snap),
      transform var(--jp-dur-1) var(--jp-ease-snap),
      border-color var(--jp-dur-1) var(--jp-ease-snap);
  }
  .topbar-menu:hover,
  .jp-m-appbar-menu:hover {
    background: var(--jp-navy-10);
    border-color: var(--jp-navy-14);
  }
  .topbar-menu:active,
  .jp-m-appbar-menu:active {
    background: var(--jp-navy-14);
    transform: scale(.94);
  }
  .topbar-menu svg,
  .jp-m-appbar-menu svg {
    width: 22px;
    height: 22px;
    display: block;
    stroke: currentColor;
    stroke-width: 2.4;
  }

  /* Back-chevron — matching pill weight on LEFT slot for symmetry */
  header.topbar .topbar-back {
    flex: 0 0 42px;
    width: 42px;
    height: 42px;
    min-height: 42px;
    background: var(--jp-navy-06);
    border: 1px solid var(--jp-navy-10);
    border-radius: var(--jp-r-md);
    box-shadow: var(--jp-shadow-sm);
    color: var(--jp-navy);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background var(--jp-dur-1) var(--jp-ease-snap), transform var(--jp-dur-1) var(--jp-ease-snap);
  }
  header.topbar .topbar-back:active {
    background: var(--jp-navy-14);
    transform: scale(.94);
  }

  /* ── Universal .grad text fix — Block 46a CANONICAL ─────────────────────
     jp-marketing-mobile-v2.css:503 has:
       body.jp-m .hero h1 .grad { color:transparent !important;
         background:linear-gradient(110deg,#fff,#6FE7E2) !important;
         -webkit-background-clip:text !important;
         -webkit-text-fill-color:transparent !important }
     That gradient was designed for DARK hero backgrounds. On the current
     LIGHT hero, the transparent fill shows the pale-blue background through
     the letters → washed out. Force solid teal-dark with !important to
     beat that rule. Higher specificity AND !important to guarantee win. */
  body.jp-m .hero h1 .grad,
  body.jp-m .hero h1 span.grad,
  .hero h1 .grad {
    background: none !important;
    background-image: none !important;
    -webkit-background-clip: initial !important;
    background-clip: initial !important;
    -webkit-text-fill-color: var(--grad-color, var(--jp-teal-dk)) !important;
    color: var(--grad-color, var(--jp-teal-dk)) !important;
    display: inline !important;
    font-weight: var(--jp-fw-black);
    opacity: 1 !important;
  }
  /* Dark-hero variant (navy-bg hero): use bright teal for contrast */
  body.jp-m .hero[data-hero-tone="dark"] h1 .grad,
  body.jp-m .hero.is-dark h1 .grad,
  body.jp-m .hero.hero-dark h1 .grad,
  .hero[data-hero-tone="dark"] h1 .grad,
  .hero.is-dark h1 .grad,
  .hero.hero-dark h1 .grad {
    --grad-color: var(--jp-teal) !important;
  }

  /* ── Primary CTA — THE brand gradient button (Block 46a bulletproof) ───
     Specificity AND !important to beat:
       jp-marketing-mobile-v2.css:512
       body.jp-m .hero .jp-btn-primary,
       body.jp-m .cta-card .jp-btn-primary { color:#0A2D6E !important; background:#fff !important }
     Without !important on -webkit-text-fill-color, iOS Safari renders text
     white-on-white because text-fill-color (from us, no !important) won the
     fill-color cascade while marketing-v2's !important won `color`. */
  body.jp-m .hero .jp-btn-primary,
  body.jp-m .hero .hero-ctas .jp-btn-primary,
  body.jp-m .cta-card .jp-btn-primary,
  .hero-ctas .jp-btn-primary,
  .cta-card .jp-btn-primary {
    background: var(--jp-grad-brand) !important;
    background-image: var(--jp-grad-brand) !important;
    color: var(--jp-on-dark) !important;
    -webkit-text-fill-color: var(--jp-on-dark) !important;
    border: none !important;
    font-family: var(--jp-font-sans);
    font-weight: var(--jp-fw-black) !important;
    font-size: var(--jp-fs-md) !important;
    letter-spacing: var(--jp-ls-tight) !important;
    padding: var(--jp-sp-3) var(--jp-sp-5) !important;
    border-radius: var(--jp-r-md) !important;
    box-shadow: var(--jp-shadow-cta) !important;
    text-decoration: none !important;
    text-align: center !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: var(--jp-sp-2) !important;
    min-height: var(--jp-tap-primary) !important;
    width: auto !important;
    transition:
      transform var(--jp-dur-1) var(--jp-ease-snap),
      box-shadow var(--jp-dur-2) var(--jp-ease-soft);
    -webkit-tap-highlight-color: transparent;
  }
  /* .jp-btn-block override (full-width primary in CTA card) */
  body.jp-m .cta-card .jp-btn-primary.jp-btn-block,
  .cta-card .jp-btn-primary.jp-btn-block {
    width: 100% !important;
  }
  body.jp-m .hero .jp-btn-primary:hover,
  body.jp-m .cta-card .jp-btn-primary:hover,
  .hero-ctas .jp-btn-primary:hover,
  .cta-card .jp-btn-primary:hover {
    color: var(--jp-on-dark) !important;
    -webkit-text-fill-color: var(--jp-on-dark) !important;
  }
  body.jp-m .hero .jp-btn-primary:active,
  body.jp-m .cta-card .jp-btn-primary:active,
  .hero-ctas .jp-btn-primary:active,
  .cta-card .jp-btn-primary:active {
    transform: scale(.985);
    box-shadow: var(--jp-shadow-cta-active) !important;
  }

  /* Ghost CTA — used as secondary in hero pair */
  .hero-ctas .jp-btn-ghost,
  body.jp-m .hero .jp-btn-ghost {
    background: transparent;
    color: var(--jp-navy);
    border: 1.5px solid var(--jp-navy-18);
    font-weight: var(--jp-fw-bold);
    font-size: var(--jp-fs-sm);
    padding: var(--jp-sp-3) var(--jp-sp-5);
    border-radius: var(--jp-r-md);
    text-decoration: none;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--jp-sp-2);
    transition: background var(--jp-dur-1) var(--jp-ease-snap);
  }
  .hero-ctas .jp-btn-ghost:active {
    background: var(--jp-navy-06);
  }

  /* ── Hero pill (eyebrow chip above H1) — Block 46a polished ────────────
     Centered horizontally with higher legibility: white-glass background
     bumped from .72 → .88 opacity, navy-stroke border, deeper teal text
     with subtle text-shadow for crispness on the blurred-globe background. */
  .hero-pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--jp-sp-2);
    background: rgba(255,255,255,.92) !important;
    border: 1px solid var(--jp-teal-32) !important;
    color: var(--jp-teal-dk) !important;
    -webkit-text-fill-color: var(--jp-teal-dk) !important;
    font-size: 11px !important;
    font-weight: var(--jp-fw-black) !important;
    letter-spacing: var(--jp-ls-wider) !important;
    text-transform: uppercase !important;
    padding: 6px 14px !important;
    border-radius: var(--jp-r-pill);
    margin: 0 auto var(--jp-sp-3) !important;        /* CENTER horizontally */
    backdrop-filter: var(--jp-blur-soft);
    -webkit-backdrop-filter: var(--jp-blur-soft);
    box-shadow: 0 2px 8px var(--jp-navy-08), 0 1px 0 rgba(255,255,255,.9) inset !important;
  }
  /* Center the hero-pill within its parent flex column */
  .hero .hero-pill,
  .hero-ctas-wrap .hero-pill {
    align-self: center;
  }
  .hero-pill-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--jp-teal);
    box-shadow: var(--jp-glow-teal);
    animation: jp-pulse-dot 2.4s ease-in-out infinite;
  }
  @keyframes jp-pulse-dot {
    0%,100% { opacity: 1; transform: scale(1); }
    50%     { opacity: .55; transform: scale(.82); }
  }

  /* ── Trust chips (compliance badges at end of hero) ─────────────────── */
  .chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--jp-sp-2);
    margin-top: var(--jp-sp-3);
    position: relative;
  }
  .chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 10px;
    font-weight: var(--jp-fw-black);
    letter-spacing: var(--jp-ls-wide);
    text-transform: uppercase;
    color: var(--jp-navy);
    background: var(--jp-glass-faint);
    border: 1px solid var(--jp-navy-10);
    padding: var(--jp-sp-1) 9px;
    border-radius: var(--jp-r-pill);
    backdrop-filter: var(--jp-blur-soft);
    -webkit-backdrop-filter: var(--jp-blur-soft);
  }
  .chip svg { width: 11px; height: 11px; }
}

  /* ── Globe flight-line animations (Block 46a) ─────────────────────────
     Mobile globe SVG has the same .globe-arc ga-1..ga-8 paths as desktop
     but no animation CSS. Port the desktop keyframes verbatim so the
     mobile hero matches the desktop motion language. Brand-consistent
     teal/teal-dk strokes already on the SVG paths.
     Honors prefers-reduced-motion — paths stay invisible (opacity:0)
     rather than animating. */
  .globe-arc { fill: none; stroke-linecap: round; opacity: 0; }
  .ga-1 { stroke-dasharray: 125; stroke-dashoffset: 125; animation: jp-ga1 5.2s ease-in-out 0.0s infinite; }
  .ga-2 { stroke-dasharray: 170; stroke-dashoffset: 170; animation: jp-ga2 6.0s ease-in-out 2.5s infinite; }
  .ga-3 { stroke-dasharray: 145; stroke-dashoffset: 145; animation: jp-ga3 5.6s ease-in-out 1.2s infinite; }
  .ga-4 { stroke-dasharray: 110; stroke-dashoffset: 110; animation: jp-ga4 4.8s ease-in-out 3.8s infinite; }
  .ga-5 { stroke-dasharray:  78; stroke-dashoffset:  78; animation: jp-ga5 4.2s ease-in-out 1.8s infinite; }
  .ga-6 { stroke-dasharray: 215; stroke-dashoffset: 215; animation: jp-ga6 7.2s ease-in-out 0.6s infinite; }
  .ga-7 { stroke-dasharray: 290; stroke-dashoffset: 290; animation: jp-ga7 8.0s ease-in-out 3.2s infinite; }
  .ga-8 { stroke-dasharray: 330; stroke-dashoffset: 330; animation: jp-ga8 8.8s ease-in-out 5.5s infinite; }

  @keyframes jp-ga1 { 0%{stroke-dashoffset:125;opacity:0} 12%{opacity:.75} 52%{stroke-dashoffset:0;opacity:.75} 78%{stroke-dashoffset:0;opacity:.30} 100%{stroke-dashoffset:0;opacity:0} }
  @keyframes jp-ga2 { 0%{stroke-dashoffset:170;opacity:0} 12%{opacity:.60} 52%{stroke-dashoffset:0;opacity:.60} 78%{stroke-dashoffset:0;opacity:.25} 100%{stroke-dashoffset:0;opacity:0} }
  @keyframes jp-ga3 { 0%{stroke-dashoffset:145;opacity:0} 12%{opacity:.65} 52%{stroke-dashoffset:0;opacity:.65} 78%{stroke-dashoffset:0;opacity:.28} 100%{stroke-dashoffset:0;opacity:0} }
  @keyframes jp-ga4 { 0%{stroke-dashoffset:110;opacity:0} 12%{opacity:.55} 52%{stroke-dashoffset:0;opacity:.55} 78%{stroke-dashoffset:0;opacity:.22} 100%{stroke-dashoffset:0;opacity:0} }
  @keyframes jp-ga5 { 0%{stroke-dashoffset: 78;opacity:0} 12%{opacity:.50} 52%{stroke-dashoffset:0;opacity:.50} 78%{stroke-dashoffset:0;opacity:.20} 100%{stroke-dashoffset:0;opacity:0} }
  @keyframes jp-ga6 { 0%{stroke-dashoffset:215;opacity:0} 10%{opacity:.55} 55%{stroke-dashoffset:0;opacity:.55} 80%{stroke-dashoffset:0;opacity:.20} 100%{stroke-dashoffset:0;opacity:0} }
  @keyframes jp-ga7 { 0%{stroke-dashoffset:290;opacity:0} 10%{opacity:.45} 55%{stroke-dashoffset:0;opacity:.45} 80%{stroke-dashoffset:0;opacity:.16} 100%{stroke-dashoffset:0;opacity:0} }
  @keyframes jp-ga8 { 0%{stroke-dashoffset:330;opacity:0} 10%{opacity:.48} 55%{stroke-dashoffset:0;opacity:.48} 80%{stroke-dashoffset:0;opacity:.18} 100%{stroke-dashoffset:0;opacity:0} }

  /* ── Hero — content lifted up tight under the topbar (Block 46a) ───── */
  .hero {
    padding-top: var(--jp-sp-3) !important;          /* Was 20px; lift it */
  }
  /* Reposition the animated globe as a background layer so content can
     overlap and start immediately under the topbar. */
  .hero-globe {
    position: absolute !important;
    top: 0 !important;
    right: 0 !important;
    width: 100% !important;
    height: 100% !important;
    pointer-events: none !important;
    z-index: 0 !important;
    overflow: hidden !important;
  }
  .hero-globe svg {
    width: 100% !important;
    height: auto !important;
    display: block !important;
  }
  /* Hero text content stacks above globe */
  .hero > :not(.hero-globe) {
    position: relative;
    z-index: 1;
  }

  /* ── CTA card eyebrow — Block 46a fix ────────────────────────────────
     The marketing-v2 rule body.jp-m .cta-card .eyebrow{color:var(--jp-mob-teal) !important}
     leaves the eyebrow on dark gradient bg with low-contrast teal. Bump to
     bright teal AND ensure it gets a glass pill treatment for legibility. */
  body.jp-m .cta-card .eyebrow,
  .cta-card .eyebrow {
    color: var(--jp-teal-lt) !important;
    -webkit-text-fill-color: var(--jp-teal-lt) !important;
    background: rgba(255,255,255,.12) !important;
    border: 1px solid rgba(255,255,255,.22) !important;
    backdrop-filter: var(--jp-blur-soft);
    -webkit-backdrop-filter: var(--jp-blur-soft);
  }

  /* Honor prefers-reduced-motion for the globe arcs */
  @media (prefers-reduced-motion: reduce) and (min-width: 99999px) {
    .globe-arc { animation: none !important; opacity: 0 !important; }
  }

  /* ── Block 48b — DARK HERO TONE (canonical fix for legibility) ─────────
     Pages with navy/dark hero backgrounds need:
       • H1 + paragraph text forced WHITE (with -webkit-text-fill-color
         also set so iOS Safari doesn't render transparent).
       • .grad span forced BRIGHT teal (--jp-teal #00C9C0), NOT teal-dark
         (which is too dark on navy bg = invisible).
       • Ghost CTA: white text + translucent-white border (navy text on
         navy bg is invisible).
       • Hero-pill chip: stays teal text on translucent-white glass.
     Auto-applied to any .hero with data-hero-tone="dark" or the legacy
     .is-dark / .hero-dark classes. Block 48b sweeps all 33 dark-hero
     mobile pages to add data-hero-tone="dark" to their <section class="hero">. */
  body.jp-m .hero[data-hero-tone="dark"] h1,
  body.jp-m .hero[data-hero-tone="dark"] h2,
  body.jp-m .hero[data-hero-tone="dark"] h3,
  body.jp-m .hero[data-hero-tone="dark"] p,
  body.jp-m .hero[data-hero-tone="dark"] li,
  body.jp-m .hero[data-hero-tone="dark"] strong,
  body.jp-m .hero[data-hero-tone="dark"] em,
  body.jp-m .hero.is-dark h1,
  body.jp-m .hero.is-dark h2,
  body.jp-m .hero.is-dark h3,
  body.jp-m .hero.is-dark p,
  body.jp-m .hero.hero-dark h1,
  body.jp-m .hero.hero-dark h2,
  body.jp-m .hero.hero-dark h3,
  body.jp-m .hero.hero-dark p {
    color: #ffffff !important;
    -webkit-text-fill-color: #ffffff !important;
  }
  body.jp-m .hero[data-hero-tone="dark"] p,
  body.jp-m .hero.is-dark p,
  body.jp-m .hero.hero-dark p {
    color: rgba(255,255,255,.88) !important;
    -webkit-text-fill-color: rgba(255,255,255,.88) !important;
  }
  /* .grad on dark hero — bright teal (defeats the auto-applied teal-dark
     from the universal .grad rule above). */
  body.jp-m .hero[data-hero-tone="dark"] h1 .grad,
  body.jp-m .hero.is-dark h1 .grad,
  body.jp-m .hero.hero-dark h1 .grad {
    --grad-color: var(--jp-teal) !important;
    color: var(--jp-teal) !important;
    -webkit-text-fill-color: var(--jp-teal) !important;
  }
  /* Ghost CTA on dark hero — white text + translucent-white border */
  body.jp-m .hero[data-hero-tone="dark"] .jp-btn-ghost,
  body.jp-m .hero[data-hero-tone="dark"] .hero-ctas .jp-btn-ghost,
  body.jp-m .hero.is-dark .jp-btn-ghost,
  body.jp-m .hero.hero-dark .jp-btn-ghost {
    color: #ffffff !important;
    -webkit-text-fill-color: #ffffff !important;
    border-color: rgba(255,255,255,.32) !important;
    background: transparent !important;
  }
  body.jp-m .hero[data-hero-tone="dark"] .jp-btn-ghost:active,
  body.jp-m .hero.is-dark .jp-btn-ghost:active {
    background: rgba(255,255,255,.08) !important;
  }
  /* Hero-pill on dark hero — translucent-white pill with bright teal text */
  body.jp-m .hero[data-hero-tone="dark"] .hero-pill,
  body.jp-m .hero.is-dark .hero-pill,
  body.jp-m .hero.hero-dark .hero-pill {
    background: rgba(255,255,255,.10) !important;
    color: var(--jp-teal) !important;
    -webkit-text-fill-color: var(--jp-teal) !important;
    border-color: rgba(0,201,192,.32) !important;
    box-shadow: 0 2px 8px rgba(0,0,0,.18), 0 1px 0 rgba(255,255,255,.08) inset !important;
  }

  /* ── Block 48b — Subtle animated background for dark heroes ─────────────
     Ports a pared-down version of the desktop's animated globe-arc
     pattern into ALL dark heroes as a background layer. Adds visual
     richness + brand consistency without requiring per-page SVG markup.
     Renders 3 floating teal blobs + 2 slow-drifting arc gradients via
     pure CSS animations (no JS). Always behind content (z-index:0). */
  body.jp-m .hero[data-hero-tone="dark"]::before,
  body.jp-m .hero.is-dark::before,
  body.jp-m .hero.hero-dark::before {
    content: '';
    position: absolute;
    top: -80px; right: -80px;
    width: 320px; height: 320px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(0,201,192,.28), transparent 65%);
    pointer-events: none;
    animation: jp-hero-blob-a 22s ease-in-out infinite alternate;
    z-index: 0;
  }
  body.jp-m .hero[data-hero-tone="dark"]::after,
  body.jp-m .hero.is-dark::after,
  body.jp-m .hero.hero-dark::after {
    content: '';
    position: absolute;
    bottom: -120px; left: -100px;
    width: 380px; height: 380px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(30,111,245,.20), transparent 60%);
    pointer-events: none;
    animation: jp-hero-blob-b 28s ease-in-out infinite alternate-reverse;
    z-index: 0;
  }
  @keyframes jp-hero-blob-a {
    0%   { transform: translate(0,0) scale(1);     opacity: .9; }
    100% { transform: translate(-30px,40px) scale(1.12); opacity: 1; }
  }
  @keyframes jp-hero-blob-b {
    0%   { transform: translate(0,0) scale(1);     opacity: .8; }
    100% { transform: translate(40px,-30px) scale(1.18); opacity: 1; }
  }
  /* Ensure hero content sits above the animated blobs */
  body.jp-m .hero[data-hero-tone="dark"] > *,
  body.jp-m .hero.is-dark > *,
  body.jp-m .hero.hero-dark > * {
    position: relative;
    z-index: 1;
  }
  @media (prefers-reduced-motion: reduce) and (min-width: 99999px) {
    body.jp-m .hero[data-hero-tone="dark"]::before,
    body.jp-m .hero[data-hero-tone="dark"]::after,
    body.jp-m .hero.is-dark::before,
    body.jp-m .hero.is-dark::after,
    body.jp-m .hero.hero-dark::before,
    body.jp-m .hero.hero-dark::after { animation: none !important; }
  }

  /* ── Block 48b — Hubs scroll-trap fix (canonical) ───────────────────────
     Horizontal-overflow regions can trap vertical pan gestures on iOS
     unless touch-action explicitly allows pan-y to fall through.
     touch-action: pan-x tells the browser "this is a horizontal scroll
     region only — let vertical pans bubble up to the document". */
  .region-chips,
  .catbar-scroll,
  .chip-row[data-horizontal-scroll],
  [data-horizontal-scroll] {
    touch-action: pan-x !important;
  }
  /* Block 48b also bumps the .region-chips sticky offset from the hard-coded
     56px (which matched the old topbar) to the new 72px Block-46a topbar height
     plus safe-area-inset-top. */
  .region-chips {
    top: calc(72px + var(--jp-sa-top, env(safe-area-inset-top, 0px))) !important;
  }

  /* ── Block 48b — Drawer CTA canonical fix ────────────────────────────────
     Belt-and-suspenders forcing the drawer's "Get a free quote →" button to
     render as navy bg + WHITE text every time, defeating any text-fill-color
     cascade interaction that previously made it render white-on-white. */
  .jp-m-drawer-cta {
    background: var(--jp-grad-brand) !important;
    background-image: var(--jp-grad-brand) !important;
    color: #ffffff !important;
    -webkit-text-fill-color: #ffffff !important;
    box-shadow: var(--jp-shadow-cta) !important;
  }
  .jp-m-drawer-cta:active {
    background: var(--jp-grad-brand) !important;
    background-image: var(--jp-grad-brand) !important;
    color: #ffffff !important;
    -webkit-text-fill-color: #ffffff !important;
    transform: scale(.985);
    box-shadow: var(--jp-shadow-cta-active) !important;
  }
  .jp-m-drawer-cta-ghost {
    color: var(--jp-navy) !important;
    -webkit-text-fill-color: var(--jp-navy) !important;
    border: 1.5px solid var(--jp-navy) !important;
  }
}

/* ============================================================================
   Block 53.6 — Scroll-driven animations (modern API where supported)
   ----------------------------------------------------------------------------
   Scroll-Driven Animations API ships in Chrome 115+ / Safari 18+.
   Where supported, the hero blobs subtly parallax-shift with page scroll;
   the existing JS-driven IntersectionObserver paths still work as fallback.
   @supports gates ensure browsers without animation-timeline ignore these.
   ========================================================================== */
@supports (animation-timeline: scroll()) {
  @media (max-width: 760px) {
    .hero::before {
      animation: jp-hero-blob-scroll-a linear both;
      animation-timeline: scroll(root);
      animation-range: 0 600px;
    }
    .hero::after {
      animation: jp-hero-blob-scroll-b linear both;
      animation-timeline: scroll(root);
      animation-range: 0 600px;
    }
    @keyframes jp-hero-blob-scroll-a {
      to { transform: translate(-60px, 80px) scale(1.18); opacity: .55; }
    }
    @keyframes jp-hero-blob-scroll-b {
      to { transform: translate(80px, -60px) scale(1.22); opacity: .55; }
    }
  }
}

/* Desktop: strict no-op (defensive — all rules above are media-gated, but
   we double-down here to make the contract explicit). */
@media (min-width: 761px) {
  /* Intentionally empty. This file does nothing on desktop. */
}
