/* =============================================================================
   PD Cash — responsive / cross-browser layer
   -----------------------------------------------------------------------------
   Sections 1-11 (2026-08-23) targeted the prerendered-React build that was
   replaced on 2026-08-25. A census across all 21 routes found every one of their
   selectors matching 0 elements, except two that were actively WRONG for this
   build:
     - section 8 zeroed scroll-margin-top below 1024px, which put every mobile
       in-page anchor under the fixed header (removed 2026-08-26, unit U18);
     - section 3 forced #mobile-navigation to display:none above 1020px, which
       would block a drawer opened in the 1021-1023px band.
   Sections 1-11 were removed on 2026-08-26 (unit U22). What remains is sections
   12-13, written for the current build.
   Loaded last on all 22 public pages. Additive and presentation-only.
   ========================================================================== */

/* ---- 12. Current-theme viewport system (2026-08-25) -------------------------
   Fluid sizing and resilient layout guards for the current Tailwind public
   shell. The black/green art direction, 1280px reading width, and existing
   component hierarchy are deliberately preserved. */
:root {
  --pd-compact-gutter: 1rem;
  --pd-touch-target: 44px;
  --pd-pointer-target: 28px;
  --pd-compact-card-radius: 1.5rem;
  --pd-wide-display-min: 3.9rem;
  --pd-wide-display-max: 4.25rem;
}

html {
  max-width: 100%;
  overflow-x: clip;
}

@supports not (overflow: clip) {
  html { overflow-x: hidden; }
}

main :is(h1, h2) {
  text-wrap: balance;
}

main :is(p, li, dd) {
  text-wrap: pretty;
}

main :is(h1, h2, h3, p, li, dd) {
  overflow-wrap: break-word;
}

main :is(.grid, .flex) > * {
  min-width: 0;
}

/* A visible but compact scrollbar should not consume 10px of a phone screen. */
@media (max-width: 1023.98px) {
  html { scrollbar-width: thin; }

  ::-webkit-scrollbar {
    width: 4px;
    height: 4px;
  }

  main input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  main select,
  main textarea {
    font-size: 16px;
  }

  footer nav :is(a, button) {
    display: inline-flex;
    min-height: var(--pd-touch-target);
    max-width: 100%;
    align-items: center;
  }
}

/* 320-359px: reclaim card/gutter space without shrinking readable body text. */
@media (max-width: 359.98px) {
  main > section > [class~="mx-auto"][class*="px-"],
  footer > [class~="relative"][class~="mx-auto"] {
    padding-inline: var(--pd-compact-gutter);
  }

  main h1.display {
    font-size: clamp(2rem, 10vw, 2.15rem);
    line-height: 1;
  }

  main .card[class~="p-7"],
  main .card[class~="p-8"],
  main .auth-card[class~="p-7"] {
    padding: 1.25rem;
  }

  #navShell {
    padding-inline: 1rem;
  }
}

/* Compact laptops: keep the full desktop navigation comfortably separated. */
@media (min-width: 1024px) and (max-width: 1180px) {
  header [class~="gap-8"] {
    gap: 1.25rem;
  }

  #navShell {
    padding-inline: 1rem;
  }
}

@media (min-width: 1024px) {
  header .nav-link,
  footer nav :is(a, button) {
    display: inline-flex;
    min-height: var(--pd-pointer-target);
    align-items: center;
  }
}

/* Short laptop viewports retain the CTA while avoiding a wasteful top gap. */
@media (min-width: 1024px) and (max-height: 720px) {
  /* Only the tall homepage hero: it starts flush under the fixed header, so 7.5rem still
     clears it while reclaiming height. The 21 breadcrumbed pages already start at y=143
     with a 3.5rem hero - applying this to them ADDS 64px instead of removing any. */
  main > section:first-child[class*="pt-28"] {
    padding-top: 7.5rem;
  }
}

/* Large desktops gain hierarchy, not wider reading lines. */
@media (min-width: 1600px) {
  main h1.display {
    font-size: clamp(
      var(--pd-wide-display-min),
      3.2vw,
      var(--pd-wide-display-max)
    );
    line-height: .98;
  }
}


/* ---- 13. Contextual interaction sizing -------------------------------------
   Standalone links and demo controls need a real hit area; prose links retain
   the WCAG inline-link exception and keep natural line flow. */
@media (max-width: 1023.98px) {
  main .card h3 > a,
  main a[class*="font-bold"],
  #ckQrToggle {
    display: inline-flex;
    min-height: var(--pd-touch-target);
    align-items: center;
  }

  label:has(> #scSearch) {
    min-height: var(--pd-touch-target);
  }
}

@media (min-width: 1024px) {
  main .card h3 > a,
  main a.inline-flex,
  main a[class*="font-bold"],
  #ckQrToggle,
  .footer-contact {
    display: inline-flex;
    min-height: var(--pd-pointer-target);
    align-items: center;
  }
}

@media (max-width: 1023.98px) { main :is(select, textarea).auth-input { font-size: 16px; } }

@media (min-width: 1600px) { main h1.display[class*="xl:text-[3.9rem]"] { font-size: 3.9rem; line-height: 1; } }

/* ---- 14. Hash-arrival landing for the /contact anchors (U21, 2026-08-27) ----
   #onboarding-form is <div class="reveal-now min-w-0" id="onboarding-form">;
   #contact-form is the sr-only <span> that is its FIRST CHILD. Both anchors
   resolve to the same box, so a .sr-only selector would miss one of them.

   Two defects compose:
   (1) OFFSET. The only anchor convention in the build is
       section[id]{scroll-margin-top:96px} - which is why /#pricing lands
       correctly. A <div> and a <span> match nothing, compute 0px, and park at
       viewport top 0 behind the 76/80px fixed header.
   (2) RESIDUE. .reveal-now{animation:revealIn .8s ... both} holds the box at
       0%{transform:translateY(26px) scale(.985)} while the browser resolves the
       fragment scroll; the box then settles 26 + 0.0075*H higher and nothing
       re-aligns. Transform only, so document height stays constant at 1977 -
       which is what rules out font swap and the IntersectionObserver pass.
       Measured live on a real top-level tab, 2026-08-27:
         1280: marker 557.01 -> 525.41 = 31.60 residue (H 745.31)
          375: marker 491.79 -> 457.97 = 33.82 residue (H 1041)

   scroll-margin-top is consumed at the instant the scroll target is computed,
   so it cancels (1) but not (2). One constant sized to header + residue absorbs
   both: 128 rests the marker at 96.41 on 1280 (17.4px clear of the 80px header)
   and 93.97 on 375 (18.0px clear of 76px) - the same resting position
   /#pricing already produces. Residue would have to exceed 48px (H > ~2900)
   to occlude again.

   px, not rem: this tracks a header specified in px, so it survives any change
   to the root size from the type scale in sections 12-13. scroll-margin has no
   layout, paint or box effect - it moves the scroll position only. */
#contact-form,
#onboarding-form {
  scroll-margin-top: 128px;
}

/* The build ships @media (prefers-reduced-motion:reduce){.reveal-now{animation:none}},
   so that cohort has residue 0 on every path and the build own 96px is exact for
   them (measured 96.41). Written as an override on a 128 base so an engine that
   cannot resolve the query fails toward whitespace, never toward occlusion. */
@media (prefers-reduced-motion: reduce) {
  #contact-form,
  #onboarding-form {
    scroll-margin-top: 96px;
  }
}

/* ---- 15. Print: the page currently prints blank (U23, 2026-08-26) ----------
   Measured on the live build, /terms:
     - @media print rule count across every stylesheet on the page: 0
     - html and body background: rgb(0, 0, 0)
     - text colour histogram in main: 164 elements rgba(255,255,255,.65),
       37 rgb(255,255,255), 22 rgba(255,255,255,.6), 2 green. No dark text.
     - 51 of the 52 .reveal blocks below the fold sit at opacity 0, because
       their IntersectionObserver has not fired for content that was never
       scrolled into view.
   Browsers omit background colours when printing unless the reader turns
   background graphics on, so today a printed Terms, Privacy or AML page is
   white text on white paper - and most of it is at opacity 0 regardless.
   Merchants and payment-partner reviewers print exactly these pages.

   This block is print-only: it cannot affect screen rendering. !important is
   used deliberately - the colours come from Tailwind utilities like
   text-white/65 (specificity 0-1-0) which an element selector cannot beat, and
   there are no competing print rules to fight. */
@media print {
  html,
  body {
    background: #fff !important;
    color: #111 !important;
  }

  /* Content that never revealed must still print. */
  .reveal,
  .reveal-now {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
    filter: none !important;
  }

  /* Text has to be legible on paper. */
  main,
  main *,
  footer,
  footer * {
    color: #111 !important;
    background-image: none !important;
    box-shadow: none !important;
    text-shadow: none !important;
  }
  main h1,
  main h2,
  main h3,
  main h4 {
    color: #000 !important;
  }
  main a,
  footer a {
    color: #00407d !important;
    text-decoration: underline;
  }

  /* Chrome and decoration waste paper; a fixed header repeats on every sheet. */
  header,
  canvas,
  .site-header,
  [aria-hidden="true"] svg {
    display: none !important;
  }

  /* Scroll containers must not clip their content on paper. */
  main *,
  footer * {
    overflow: visible !important;
    max-height: none !important;
  }

  /* Do not split a heading from the text it introduces. */
  h1, h2, h3, h4 {
    break-after: avoid-page;
    page-break-after: avoid;
  }
  p, li, tr, img, figure {
    break-inside: avoid;
    page-break-inside: avoid;
  }
}


/* ---- 14. Collapsed disclosure regions must not be exposed to assistive tech ---
   .faq-a and .cmp-panel collapse with grid-template-rows:0fr plus overflow:hidden on the
   inner div. That clips them visually but leaves the text in the accessibility tree, so a
   screen reader reads every answer while the control reports aria-expanded="false"
   (WCAG 2.2 SC 4.1.2 Name, Role, Value).

   Gated on .pd-a11y, set by this layer's own JS: if that script does not run the rules never
   apply and behaviour is exactly as before, so no content is stranded. The hide is delayed by
   each panel's own transition duration so content does not disappear mid-close; showing is
   immediate. visibility is inherited, so one declaration covers the whole subtree. */
.pd-a11y .faq-a > div {
  visibility: hidden;
  transition: visibility 0s linear .38s;
}
.pd-a11y .faq-item.is-open .faq-a > div {
  visibility: visible;
  transition-delay: 0s;
}
.pd-a11y .cmp-panel > div {
  visibility: hidden;
  transition: visibility 0s linear .45s;
}
.pd-a11y .cmp-panel.is-open > div {
  visibility: visible;
  transition-delay: 0s;
}


/* ---- 15. Authored swipe cues follow measurement, not a viewport number -------
   "Swipe horizontally to compare both plans." is authored with sm:hidden, so it stays on
   screen from ~602px to 639px after the table has stopped overflowing. markScrollers() sets
   data-pd-cue from scrollWidth-clientWidth, and these two rules let that measurement win.
   Element+attribute (0,1,1) outranks the utility class (0,1,0), and this sheet loads after
   the bundle, so no !important is needed. */
p[data-pd-cue="off"] { display: none; }
p[data-pd-cue="on"]  { display: block; }

/* Keep the fixed mobile menu reachable on short landscape screens. */
@media (max-width: 1023.98px) {
  #mobile-navigation {
    max-height: calc(100vh - 88px - var(--pd-compact-gutter) - env(safe-area-inset-bottom, 0px));
    max-height: calc(100dvh - 88px - var(--pd-compact-gutter) - env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
  }
}

/* The stacked mobile hero stays interactive while the page scrolls. */
@media (max-width: 1023.98px) {
  #heroCopy,
  #heroVisual {
    opacity: 1 !important;
  }
}


/* ---- 16. Public mobile polish (2026-09-06) --------------------------------
   Preserve the current dark/green theme while fitting card geometry to narrow
   screens. Contact path descriptions are decision-making copy, so they wrap
   instead of disappearing behind an ellipsis at 320px. */
@media (max-width: 639.98px) {
  main .card {
    border-radius: var(--pd-compact-card-radius);
  }
}

#onboarding-form .path-tab > .min-w-0 > .truncate {
  overflow: visible;
  white-space: normal;
  text-overflow: clip;
  text-wrap: pretty;
  line-height: 1.5;
}

@media (max-width: 1023.98px) {
  #mobileCta .pill {
    min-height: var(--pd-touch-target);
  }
}

