/* Floating WeChat card (partials/wechat-float.php).
   Its own file because it renders on pages with either skin: site.css pages
   and the guides index, which loads only article.css. index.php adds this
   stylesheet under the same !$isGuideArticle gate that renders the card.
   Variables used here are defined in site.css or carry a fallback. */

/* ---------- Floating WeChat card ---------- */
/* Stacked above .am-to-top (back-to-top.js pins it at right:16/bottom:16, 44x44,
   z-index 45): 16 + 44 + 12 = 72px, reusing that button's own 12px gap.
   z-index 42 keeps it under the button (which must stay clickable) and far under
   .lightbox (100), so enlarging a code still covers this card.
   The footer contact block is deliberately kept as well — this card needs JS for
   the overlay, the footer one is a plain <a href> that works without it. */
.wechat-float {
  position: fixed;
  right: 16px;
  bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  z-index: 42;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px;
  border-radius: 12px;
  background: var(--ink-soft, #fff);
  border: 1px solid var(--ink-line, #e8edf4);
  box-shadow: 0 6px 20px rgba(15, 23, 42, .12);
}

/* Held back until the reader has moved past the opening screen. Two reasons, and
   the second is the load-bearing one:
   · the homepage hero puts a wide product shot outside the text column, so a card
     positioned against .container (1140px) still lands on top of it — the one
     place on this site where this float covers something that matters;
   · the opening screen already carries three CTAs. decisions.md turned a floating
     contact button down precisely because a permanent corner control steals from
     them. Appearing after the fold answers that objection rather than ignoring it.

   ⚠️ This was first wired to .am-to-top's visibility via :has(), on the theory
   that one shared threshold could not drift. **That was wrong and shipped broken
   on 2026-09-09.** back-to-top uses `scrollY > innerHeight`, which a page under
   two screens tall can never satisfy — and /demo, having just lost its hero, is
   1.77 screens. The card therefore never appeared on the one page the cold-email
   channel actually lands on. Static checks, the build, and a stand-in page all
   passed; only walking the deployed site caught it.
   The two controls want different thresholds, so they now compute them
   separately. See partials/wechat-float.php for the rule. */
.wechat-float { opacity: 0; visibility: hidden; transform: translateY(8px); }
.wechat-float.is-shown { opacity: 1; visibility: visible; transform: none; }
.wechat-float { transition: opacity .2s ease, transform .2s ease; }
@media (prefers-reduced-motion: reduce) { .wechat-float { transition: none; } }

.wechat-float-link { display: block; line-height: 0; cursor: zoom-in; border-radius: 6px; }
.wechat-float-link:focus-visible { outline: 2px solid var(--electric, #2563eb); outline-offset: 3px; }
.wechat-float-qr { display: block; width: 88px; height: 88px; border-radius: 6px; }
.wechat-float-tip {
  max-width: 88px;
  font-size: 12px;
  line-height: 1.3;
  text-align: center;
  color: var(--fg-muted);
}
/* Phones: a 108px-wide card parked over the content is a bigger cost on a narrow
   screen than the contact shortcut is worth, so the code shrinks rather than the
   card being dropped — a Chinese seller on a phone is exactly who this is for. */
@media (max-width: 640px) {
  /* Same 12px gap as desktop, not less: these are two tappable targets sitting in
     one corner, and 8px between them was close enough to mis-hit. */
  .wechat-float { padding: 8px; gap: 4px; bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
  .wechat-float-qr { width: 64px; height: 64px; }
  /* The caption sets the card's width here rather than being clamped to the code:
     capped at 64px, 「有问题？扫我」wrapped onto two lines and the card grew taller
     than it would have by simply being one line wider. Measured, not guessed. */
  .wechat-float-tip { max-width: none; font-size: 11px; white-space: nowrap; }
}
/* Wide screens: stop hugging the viewport corner and follow the content instead.
   The container is `--max: 1140px` centred, so its right edge sits at
   50vw + 570px; +16px of air puts the card's LEFT edge clear of the text, and the
   card is 110px wide — hence 50vw - 696px. Below 1424px that value drops under
   16px, which is exactly where the default corner placement takes over, so the
   two rules meet without a gap and nothing has to be repeated.

   The back-to-top button travels with it via the sibling combinator: both are
   direct children of <body> (back-to-top.js does document.body.appendChild), and
   .wechat-float ~ .am-to-top (0,2,0) outweighs the .am-to-top (0,1,0) rule that
   script injects later. Guide articles have no .wechat-float, so their button —
   and its .is-raised dance around the CTA pill — is untouched by design.

   Vertical: raised off the bottom edge so the pair reads as attached to the
   content rather than parked in the corner. Only on wide screens; on a phone
   there is no spare margin to move into and the corner is the right place. */
@media (min-width: 1424px) {
  .wechat-float { right: calc(50vw - 696px); bottom: calc(28vh + 56px); }
  .wechat-float ~ .am-to-top { right: calc(50vw - 696px); bottom: 28vh; }
}

/* The demo page offers "print / save as PDF"; a fixed card would land on top of
   whatever is under it in the printout. */
@media print { .wechat-float { display: none; } }
