/* ============================================================
   EngageDM — Landing page

   MOBILE FIRST, LITERALLY
   -----------------------
   Every base rule in this file is the 375px phone case. Larger screens
   are added with `min-width` only. There is not one `max-width` query
   here, which is the mechanical guarantee that the phone layout is the
   designed one rather than the desktop layout squeezed.

   Breakpoints:  base (phone) → 600 (large phone) → 900 (tablet) → 1200 (desktop)

   WHY IT LOOKS LIKE THIS
   ----------------------
   The page is printed matter laid on a desk. paper.css supplies the
   stock, the grain and the .sheet physics; this file arranges them.

   - SHOW, DON'T EXPLAIN. The product is demonstrated with small CSS
     mock-ups of the actual thing — a comment, a DM, a tap — not
     described in paragraphs. Prose is capped at one short line per idea.
   - NO ICON SQUARES. A pastel rounded square beside every feature is
     the most recognisable template tell there is.
   - DEPTH IS PHYSICAL. Sheets lift and tilt toward the pointer under a
     fixed light. No glows, no glass, no coloured halos.

   NO FIGURE IS HARDCODED. Numbers come from landingStats.service.js
   (DB counts cached 6h, published only above a floor, backfilled with
   live config constants) or from planFeatures.

   JS CONTRACT (public/js/lp.js + public/js/paper.js)
   .lx-reveal, [data-tilt], #lxStamp, #lpCycleTabs .lp-cycle-tab
   [data-cycle], #proTotalPrice, #proPerAccount, #proCtaBtn,
   #accountCount, #stepperMinus, #stepperPlus, #scrollProgress.
============================================================ */

/* ============================================================
   1. SCOPE + SCALE
============================================================ */
body.lpx {
  /* Geometric sans, heavy, tight. The display face WAS Instrument Serif;
     a high-contrast serif plus a warm accent plus generous whitespace is
     the fashion-house formula, not a software one. Plus Jakarta Sans is
     already loaded for body copy, so this costs no extra request. */
  --lx-display: var(--font-ui);
  --lx-sans:  var(--font-ui);
  --lx-data:  'Space Grotesk', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Phone-first type. The lower bound of every clamp is the value the
     375px screen actually gets, so it is chosen first and the desktop
     ceiling second. Body never drops below 16px. */
  --lx-t-mast: clamp(33px, 6.6vw, 62px);
  --lx-t-sec:  clamp(24px, 3.8vw, 38px);
  --lx-t-fig:  clamp(24px, 5.6vw, 36px);
  --lx-t-lead: clamp(16px, 2.4vw, 18px);
  --lx-t-meta: 11.5px;

  --lx-gut: 18px;
  --lx-max: 1240px;
  --lx-pad: 52px;         /* section rhythm — grows at each breakpoint */
  --lx-spine: 0px;        /* the printed margin; desktop only */

  --lx-rule: var(--border-subtle);
  --lx-rule-strong: var(--border-strong);

  font-family: var(--lx-sans);
  color: var(--text-primary);
  overflow-x: hidden;     /* belt and braces against a stray wide child */
}

@media (min-width: 600px) { body.lpx { --lx-gut: 26px; --lx-pad: 64px; } }
@media (min-width: 900px) { body.lpx { --lx-gut: 34px; --lx-pad: 80px; } }
@media (min-width: 1200px) {
  body.lpx { --lx-gut: 44px; --lx-pad: 96px; --lx-spine: 88px; }
}

body.lpx .lx-data,
body.lpx .lx-fig__val,
body.lpx .lx-amount,
body.lpx .lx-step__n {
  font-family: var(--lx-data);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ============================================================
   2. SHELL
============================================================ */
body.lpx .lx-shell {
  max-width: var(--lx-max);
  margin-inline: auto;
  padding-inline: var(--lx-gut);
}

/* Single column on a phone. The spine only exists once there is a margin
   wide enough to print into. */
body.lpx .lx-sec {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding-block: var(--lx-pad);
  border-top: 1px solid var(--lx-rule);
}
@media (min-width: 1200px) {
  body.lpx .lx-sec { grid-template-columns: var(--lx-spine) minmax(0, 1fr); }
}

body.lpx .lx-sec__idx {
  font-family: var(--lx-data);
  font-size: var(--lx-t-meta);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}
@media (min-width: 1200px) {
  body.lpx .lx-sec__idx { margin-bottom: 0; padding-top: 0.7em; }
}

body.lpx .lx-sec__body { min-width: 0; }

body.lpx .lx-h {
  font-family: var(--lx-display);
  font-weight: 800;
  font-size: var(--lx-t-sec);
  line-height: 1.04;
  letter-spacing: -0.028em;
  margin: 0 0 16px;
  text-wrap: balance;
}
body.lpx .lx-h em { font-style: normal; color: var(--accent); }

/* One short line per idea. If a lede needs two sentences the section is
   trying to do two things. */
body.lpx .lx-lede {
  font-size: var(--lx-t-lead);
  line-height: 1.55;
  color: var(--text-body, var(--text-secondary));
  max-width: 46ch;
  margin: 0 0 32px;
}

/* ============================================================
   3. MASTHEAD
============================================================ */
body.lpx .lx-mast {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding-block: 40px 8px;
}
@media (min-width: 1200px) {
  body.lpx .lx-mast { grid-template-columns: var(--lx-spine) minmax(0, 1fr); padding-block: 64px 16px; }
}

/* The masthead's spine mark is a printer's colophon, not a label — it means
   nothing stranded above the headline on a phone, so it appears only once
   there is a margin to print it into. */
body.lpx .lx-mast .lx-sec__idx { display: none; }
@media (min-width: 1200px) { body.lpx .lx-mast .lx-sec__idx { display: block; } }

body.lpx .lx-kicker {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--lx-data);
  font-size: var(--lx-t-meta);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 18px;
}
body.lpx .lx-kicker::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--lx-rule);
}

body.lpx .lx-mast__title {
  font-family: var(--lx-display);
  font-weight: 800;
  font-size: var(--lx-t-mast);
  line-height: 0.95;
  letter-spacing: -0.035em;
  margin: 0 0 18px;
  max-width: 14ch;
}
body.lpx .lx-mast__title em { font-style: normal; color: var(--accent); }

body.lpx .lx-mast__lede {
  font-size: var(--lx-t-lead);
  line-height: 1.55;
  color: var(--text-body, var(--text-secondary));
  max-width: 40ch;
  margin: 0 0 26px;
}

/* Stack on a phone; the demo moves alongside only when there is width for
   both to stay readable. */
body.lpx .lx-mast__cols { display: grid; gap: 36px; }
@media (min-width: 900px) {
  body.lpx .lx-mast__cols {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
    gap: 52px;
    align-items: center;
  }
}

/* ── Actions ──────────────────────────────────────────────
   Full-width stacked buttons on a phone: a thumb reaching across a 375px
   screen should not have to aim. They become inline from 600px up. */
body.lpx .lx-actions { display: grid; gap: 12px; }
@media (min-width: 600px) {
  body.lpx .lx-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 24px;
  }
}

body.lpx .lx-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 52px;
  padding: 0 26px;
  border: 1px solid transparent;
  border-radius: var(--sheet-radius);
  background: var(--brand-fill);
  /* White on champagne gold is 2.3:1 and fails. --text-on-brand is the
     near-black that passes in both themes. */
  color: var(--text-on-brand);
  font-family: var(--lx-sans);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--sheet-rest);
  transition: background 0.18s ease, box-shadow 0.28s cubic-bezier(0.16,1,0.3,1), transform 0.28s cubic-bezier(0.16,1,0.3,1);
}
@media (hover: hover) and (pointer: fine) {
  body.lpx .lx-cta:hover {
    background: var(--accent-3);
    box-shadow: var(--sheet-lift);
    transform: translateY(-2px);
  }
}
body.lpx .lx-cta:active { transform: translateY(1px); box-shadow: var(--sheet-press); }

body.lpx .lx-cta2 {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 4px;
  color: var(--text-primary);
  font-size: 16px;
  font-weight: 650;
  text-decoration: none;
  border-bottom: 1px solid var(--lx-rule-strong);
  transition: color 0.18s ease, border-color 0.18s ease;
}
body.lpx .lx-cta2:hover { color: var(--accent); border-bottom-color: var(--accent); }

body.lpx .lx-note {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-muted);
  margin: 16px 0 0;
}

/* ============================================================
   4. VISUAL MOCK-UPS
   Small CSS renderings of the real thing. They exist so the page can
   SHOW a comment becoming a DM instead of describing it — no images,
   no icon fonts, nothing to load.
============================================================ */
body.lpx .viz {
  display: grid;
  gap: 10px;
  padding: 16px;
}

/* An Instagram comment row. */
body.lpx .viz-cmt { display: flex; gap: 10px; align-items: flex-start; }
body.lpx .viz-av {
  width: 32px; height: 32px;
  flex: none;
  border-radius: 50%;
  background: var(--bg-elevated-2);
  border: 1px solid var(--lx-rule);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
}
body.lpx .viz-cmt__b { min-width: 0; }
body.lpx .viz-who {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-muted);
  margin-bottom: 3px;
}
body.lpx .viz-txt {
  font-size: 15.5px;
  line-height: 1.45;
  color: var(--text-primary);
  margin: 0;
}

/* The outgoing DM. Aligned right and inked in gold, so the direction of
   the exchange is legible without a label. */
body.lpx .viz-dm {
  align-self: flex-end;
  max-width: 88%;
  margin-left: auto;
  padding: 12px 14px;
  border-radius: 14px 14px 3px 14px;
  background: var(--brand-fill);
  color: var(--text-on-brand);
  box-shadow: var(--sheet-rest);
}
body.lpx .viz-dm p { margin: 0; font-size: 15px; line-height: 1.45; font-weight: 500; }
body.lpx .viz-dm__btn {
  display: block;
  margin-top: 10px;
  padding: 9px 12px;
  border-radius: 4px;
  background: rgba(28, 25, 23, 0.13);
  font-size: 13.5px;
  font-weight: 700;
  text-align: center;
}

/* The connector between the two. A printed arrow, not a border. */
/* --brand-strong, not --accent. This label also sits inside .lx-step__viz,
   whose recessed --bg-sunken ground is darker than a sheet — enough to drop
   the standard bronze from 5.04:1 to 4.42:1 and just miss AA at 11px. */
body.lpx .viz-arrow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--lx-data);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand-strong, var(--accent));
}
body.lpx .viz-arrow::before,
body.lpx .viz-arrow::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--lx-rule-strong), transparent);
}

/* ============================================================
   5. FIGURE STRIP
   Two-up on a phone, four-up from tablet. Each figure is its own small
   sheet so the strip reads as a set of filing cards.
============================================================ */
body.lpx .lx-strip { margin-top: 40px; }

body.lpx .lx-strip__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
@media (min-width: 900px) {
  body.lpx .lx-strip__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
}

body.lpx .lx-fig { padding: 16px 14px 18px; min-width: 0; }
@media (min-width: 900px) { body.lpx .lx-fig { padding: 20px 18px 22px; } }

body.lpx .lx-fig__val {
  display: block;
  font-size: var(--lx-t-fig);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  margin-bottom: 9px;
}
body.lpx .lx-fig--live .lx-fig__val { color: var(--accent); }

body.lpx .lx-fig__lab {
  display: block;
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 4px;
}
body.lpx .lx-fig__note {
  display: block;
  font-size: 12.5px;
  line-height: 1.42;
  color: var(--text-muted);
}
/* The explanatory line is the first thing to go when space is tight — the
   figure and its label carry the meaning on their own. */
@media (max-width: 599px) {
  body.lpx .lx-fig__note { display: none; }
}

body.lpx .lx-stamp {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  margin: 14px 0 0;
  font-family: var(--lx-data);
  font-size: var(--lx-t-meta);
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
body.lpx .lx-stamp__dot {
  width: 6px; height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--accent);
}

/* ============================================================
   6. STEPS
   Three big visual cards. One line of copy each — the mock-up above it
   is doing the explaining.
============================================================ */
body.lpx .lx-steps {
  display: grid;
  gap: 16px;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 900px) {
  body.lpx .lx-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
}

body.lpx .lx-step { padding: 20px 18px 22px; display: flex; flex-direction: column; }
@media (min-width: 900px) { body.lpx .lx-step { padding: 24px 22px 26px; } }

body.lpx .lx-step__n {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--accent);
  margin-bottom: 14px;
}

/* The mock-up sits in a recessed well, the way a print sample is mounted. */
body.lpx .lx-step__viz {
  background: var(--bg-sunken);
  border: 1px solid var(--lx-rule);
  border-radius: 3px;
  margin-bottom: 16px;
  min-height: 118px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

body.lpx .lx-step__h {
  font-family: var(--lx-display);
  font-size: 24px;
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.012em;
  margin: 0 0 6px;
}
body.lpx .lx-step__p {
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-body, var(--text-secondary));
  margin: 0;
}

/* ============================================================
   7. USE-CASE TILES
   What a creator actually does with it, in three words each.
============================================================ */
body.lpx .lx-tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
@media (min-width: 700px)  { body.lpx .lx-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; } }
@media (min-width: 1100px) { body.lpx .lx-tiles { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

body.lpx .lx-tile {
  padding: 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 108px;
}
body.lpx .lx-tile__kw {
  align-self: flex-start;
  padding: 4px 9px;
  border: 1px dashed var(--accent);
  border-radius: 3px;
  font-family: var(--lx-data);
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
}
body.lpx .lx-tile__t {
  font-size: 14px;
  font-weight: 650;
  line-height: 1.35;
  color: var(--text-primary);
  margin: auto 0 0;
}

/* ============================================================
   8. PRICE
============================================================ */
body.lpx .lx-price { display: grid; gap: 28px; }
@media (min-width: 900px) {
  body.lpx .lx-price { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 44px; align-items: start; }
}

/* Cycle tabs wrap to two rows on a phone rather than shrinking below the
   44px touch minimum. */
body.lpx .lx-cycles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--lx-rule-strong);
  border-radius: var(--sheet-radius);
  overflow: hidden;
  margin-bottom: 22px;
}
@media (min-width: 600px) { body.lpx .lx-cycles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

body.lpx .lx-cycles .lp-cycle-tab {
  min-height: 46px;
  padding: 11px 8px;
  border: 0;
  border-left: 1px solid var(--lx-rule);
  border-top: 1px solid var(--lx-rule);
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--lx-sans);
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}
body.lpx .lx-cycles .lp-cycle-tab:nth-child(-n+2) { border-top: 0; }
body.lpx .lx-cycles .lp-cycle-tab:nth-child(odd)  { border-left: 0; }
@media (min-width: 600px) {
  body.lpx .lx-cycles .lp-cycle-tab { border-top: 0; }
  body.lpx .lx-cycles .lp-cycle-tab:nth-child(odd) { border-left: 1px solid var(--lx-rule); }
  body.lpx .lx-cycles .lp-cycle-tab:first-child    { border-left: 0; }
}
body.lpx .lx-cycles .lp-cycle-tab:hover { background: var(--bg-elevated-2); color: var(--text-primary); }
body.lpx .lx-cycles .lp-cycle-tab.active { background: var(--brand-fill); color: var(--text-on-brand); }

body.lpx .lx-amount {
  font-size: clamp(40px, 12vw, 68px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.035em;
  margin: 0 0 8px;
}
body.lpx .lx-amount .per-period {
  font-size: 0.32em;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0;
}
body.lpx .lx-amount__sub {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-muted);
  margin: 0 0 22px;
}

body.lpx .lx-stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--lx-rule-strong);
  border-radius: var(--sheet-radius);
  overflow: hidden;
}
body.lpx .lx-stepper .stepper-btn {
  width: 48px; height: 48px;
  border: 0;
  background: transparent;
  color: var(--text-primary);
  font-size: 20px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}
body.lpx .lx-stepper .stepper-btn:hover:not(:disabled) { background: var(--bg-elevated-2); color: var(--accent); }
body.lpx .lx-stepper .stepper-btn:disabled { opacity: 0.32; cursor: not-allowed; }
body.lpx .lx-stepper .stepper-count {
  min-width: 56px;
  line-height: 48px;
  text-align: center;
  font-family: var(--lx-data);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  font-weight: 600;
  border-inline: 1px solid var(--lx-rule);
}

/* ============================================================
   9. LEDGER + Q&A
============================================================ */
body.lpx .lx-ledger { border-top: 1px solid var(--lx-rule-strong); }

body.lpx .lx-row {
  display: grid;
  gap: 5px;
  padding: 18px 0;
  border-bottom: 1px solid var(--lx-rule);
}
@media (min-width: 800px) {
  body.lpx .lx-row { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.5fr); gap: 26px; align-items: baseline; }
}
body.lpx .lx-row__k { font-size: 16.5px; font-weight: 700; letter-spacing: -0.012em; }
body.lpx .lx-row__v { font-size: 15px; line-height: 1.55; color: var(--text-body, var(--text-secondary)); }

body.lpx .lx-qa { border-top: 1px solid var(--lx-rule-strong); }
body.lpx .lx-qa__item {
  display: grid;
  gap: 8px;
  padding: 20px 0;
  border-bottom: 1px solid var(--lx-rule);
}
@media (min-width: 800px) {
  body.lpx .lx-qa__item { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.4fr); gap: 34px; }
}
body.lpx .lx-qa__q {
  font-family: var(--lx-display);
  font-size: 21px;
  font-weight: 400;
  line-height: 1.2;
  margin: 0;
}
body.lpx .lx-qa__a {
  font-size: 15px;
  line-height: 1.6;
  color: var(--text-body, var(--text-secondary));
  margin: 0;
}
body.lpx .lx-qa__a a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }

/* ============================================================
   10. CLOSE
============================================================ */
body.lpx .lx-close {
  padding-block: var(--lx-pad);
  border-top: 1px solid var(--lx-rule-strong);
  text-align: center;
}
body.lpx .lx-close__h {
  font-family: var(--lx-display);
  font-weight: 800;
  font-size: clamp(30px, 8vw, 68px);
  line-height: 1.03;
  letter-spacing: -0.032em;
  margin: 0 auto 16px;
  max-width: 15ch;
}
body.lpx .lx-close__h em { font-style: normal; color: var(--accent); }
body.lpx .lx-close__p {
  font-size: var(--lx-t-lead);
  line-height: 1.55;
  color: var(--text-body, var(--text-secondary));
  max-width: 44ch;
  margin: 0 auto 26px;
}
@media (min-width: 600px) { body.lpx .lx-close .lx-actions { justify-content: center; } }

/* ============================================================
   11. MOTION + FOCUS
   Default state is VISIBLE. The hidden state only exists where motion
   is welcome, so a blocked or failed script can never leave the page
   blank — the failure mode of every scroll-reveal library.
============================================================ */
/* The hidden state is gated on html.js, which an inline script in <head>
   sets before first paint. Without JS the rule never applies and every
   section is simply visible — the alternative (hiding in plain CSS and
   relying on an observer to undo it) turns any script failure, blocked
   bundle or unsupported browser into a blank page, which is the classic
   failure of scroll-reveal. Gating on a pre-paint class also avoids the
   flash that adding the class from the deferred bundle would cause. */
/* `translate`, NOT `transform`. Several elements are both .lx-reveal and
   [data-tilt], and the reveal's resting `transform: none` has far higher
   specificity than the tilt rule — so writing this as a transform silently
   cancelled the 3D tilt on exactly the sheets that use it. `translate` is an
   independent property that composes with `transform` instead of replacing
   it, so the two effects no longer fight. */
@media (prefers-reduced-motion: no-preference) {
  html.js body.lpx .lx-reveal {
    opacity: 0;
    translate: 0 12px;
    transition: opacity 0.5s cubic-bezier(0.16,1,0.3,1), translate 0.5s cubic-bezier(0.16,1,0.3,1);
  }
  html.js body.lpx .lx-reveal.is-in { opacity: 1; translate: 0 0; }
}

body.lpx a:focus-visible,
body.lpx button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
