/* =============================================================================
   v2-buy-v20260508b.css — IMPECCABLE buy-page layer
   Loaded LAST in /buy/index.html. Additive only. Does NOT redefine any
   existing class semantics — supplements the cascade with WCAG 2.2 AA fixes,
   CTA microcopy slots, scroll-cadence reveals, focus order, dark-mode parity,
   and tightened pricing rhythm.

   Brand canon enforced:
     • Cream #faf9f5 ground, ink dark text, brand orange #c9613f only accent.
     • Fraunces serif for display, Inter for UI, no other accents introduced.
     • Voice-safe class names — no banned words bleed into copy.

   Order of concerns in this file:
     1. Tokens & sr-only utility (used by HTML markup we just added)
     2. Banner price typography (banner was/now rhythm)
     3. Hero trust-line under hero CTAs
     4. Product card depth, ring + alignment grid
     5. Pricing strike-through rhythm (was / now / pct)
     6. Buy button hover/active/focus states distinguishable in BOTH modes
     7. Per-kit trust microcopy line
     8. IntersectionObserver-friendly stagger reveal
     9. Focus-order tightening (CTA in tab path after card)
    10. Sticky CTA non-collision rule (no covering kit content)
    11. Card-grid alignment at 320 / 375 / 414 / 640 / 768 / 1024 / 1440
    12. Dark mode parity for every new element
    13. Reduced-motion fallback
    14. Print: hide CTAs cleanly
   ============================================================================= */


/* ─── 1. TOKENS & sr-only utility ─────────────────────────────────────────────
   We don't redefine palette tokens — we only consume the existing ones from
   theme.css and style.css (--accent, --ink, --bg, --rule-gray, --muted, etc.).
   The .sr-only utility is required by the new <span class="sr-only"> nodes we
   introduced in /buy/index.html for accessible price wording.
   ============================================================================= */
.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}


/* ─── 2. BANNER PRICE TYPOGRAPHY ──────────────────────────────────────────────
   The launch banner exposes "$4.99 (was $9.99–$49)". Visually, the "$4.99"
   should read first (live price) and the "(was …)" should be a calmer, struck
   companion that doesn't compete. Aria-label on the wrapper handles the
   "originally" reading; the visual cue is the line-through + opacity drop.
   ============================================================================= */
.deskrune-sale-banner .dr-banner-price {
  font-weight: 700;
  letter-spacing: 0.01em;
  /* High-contrast on the orange banner — keep white. */
  color: #faf9f5;
}
.deskrune-sale-banner .dr-banner-was {
  /* Strike-through with calmer cream tint so it reads as historical context,
     not a parallel offer. Keeps WCAG-AA contrast (4.5:1) on the orange. */
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  text-decoration-skip-ink: none;
  opacity: 0.78;
  font-weight: 400;
  font-style: italic;
  margin-left: 2px;
}
@media (max-width: 480px) {
  /* On 320–479 widths the banner already wraps; tighten the (was …) so it
     drops gracefully to a second line without leaving an orphan paren. */
  .deskrune-sale-banner .dr-banner-was {
    font-size: 0.86em;
    white-space: nowrap;
  }
}


/* ─── 3. HERO TRUST-LINE under primary CTAs ───────────────────────────────────
   Conversion principle: every CTA gets a trust microcopy companion within ~24px.
   Stripe-secured / refund / instant download — but the brand canon says be
   plain, so we say "Gumroad-secured checkout. Refund any time. Instant download."
   The line is sr-only-friendly via aria-label on the wrapper; visually it's a
   muted Inter caption that doesn't pull the eye away from the buttons.
   ============================================================================= */
.hero-trust-line {
  margin: 14px 0 0;
  font-family: var(--sans, 'Inter', system-ui, sans-serif);
  font-size: 0.86rem;
  letter-spacing: 0.01em;
  color: var(--muted, #6b6960);
  /* Limit reading width so it never spills into the badge column. */
  max-width: 56ch;
}
:root[data-theme="dark"] .hero-trust-line {
  color: #c8c0b0; /* AA on dark surface — matches --ds-ink-soft tone */
}


/* ─── 4. PRODUCT CARD DEPTH + RING + ALIGNMENT GRID ───────────────────────────
   The pre-existing card uses `box-shadow: 0 18px 50px rgba(15,23,42,0.08)` for
   the featured one and a flat 0.5px rule for the rest. That reads "flat" and
   muddy in dark mode. We layer a TINTED shadow (orange-toned) for the featured
   card, a subtle elevation 1 for the rest, and a 1px keyline that shifts to
   accent on hover/focus-within — using only the brand orange.
   We also enforce CSS Grid template rows so prices and CTAs line up across the
   row regardless of description length, which previously caused jagged edges
   at 768px.
   ============================================================================= */
.live-product {
  /* 4a. Internal layout: title → desc → spacer → price → CTA → trust-line.
         Using subgrid is overkill here; we use grid-auto-rows + min-content
         pinning for the price/CTA pair. */
  display: grid !important;
  grid-template-rows:
    auto                /* meta tag */
    auto                /* heading */
    1fr                 /* description (flex space) */
    auto                /* price */
    auto                /* CTAs */
    auto;               /* trust-line */
  gap: 14px;

  /* 4b. Calmer base elevation — 1px tinted ink shadow so it survives both
         the cream and dark grounds. */
  box-shadow:
    0 1px 0 rgba(26, 24, 20, 0.04),
    0 8px 22px rgba(26, 24, 20, 0.06);

  /* 4c. Smooth transition for hover/focus-within ring. Excludes layout
         properties so we don't trigger reflows. */
  transition:
    box-shadow 0.22s cubic-bezier(0.2, 0, 0, 1),
    border-color 0.22s cubic-bezier(0.2, 0, 0, 1),
    transform 0.22s cubic-bezier(0.2, 0, 0, 1);
  will-change: transform, box-shadow;
}

.live-product:hover,
.live-product:focus-within {
  /* Lift the card slightly. Keep transform tiny — 2px is enough to feel
     interactive without disturbing the grid alignment for neighbours. */
  transform: translateY(-2px);
  border-color: rgba(201, 97, 63, 0.35);
  box-shadow:
    0 1px 0 rgba(201, 97, 63, 0.12),
    0 14px 30px rgba(201, 97, 63, 0.10),
    0 22px 60px rgba(26, 24, 20, 0.08);
}

.live-product.featured {
  /* Featured = clearer accent ring + warmer shadow. */
  border-color: rgba(201, 97, 63, 0.65);
  box-shadow:
    0 1px 0 rgba(201, 97, 63, 0.10),
    0 18px 44px rgba(201, 97, 63, 0.12),
    0 26px 70px rgba(26, 24, 20, 0.07);
}

/* The "Fastest first buy" / "Most useful" / etc. badge — keep the existing
   accent-dark color (canonical) but ensure it has spacing breathing room,
   especially when the card grows wider on 1440. */
.live-product .live-product-meta {
  margin-bottom: 2px;
}


/* ─── 5. PRICING STRIKE-THROUGH RHYTHM ────────────────────────────────────────
   The HTML now wraps the original price in a real <s> element with sr-only
   "Was " context and the new price with sr-only "now " context (so a screen
   reader hears: "Price: four ninety-nine, down from thirty-seven dollars").
   Visually we tighten the rhythm: was-price drops to 0.85em with a calm
   cross-stroke and italic, now-price gets a subtle accent ring (carried over
   from sale-conversion.css) but with a tighter inset and a small accent-soft
   wash so it reads as the live offer at a glance.
   ============================================================================= */
.live-price.on-sale {
  /* Use baseline alignment so the dollar signs sit on the same baseline. */
  align-items: baseline;
  flex-wrap: wrap;
  row-gap: 4px;
}
.live-price.on-sale s.price-was,
.live-price.on-sale .price-was {
  font-size: 0.78em;
  color: var(--muted, #6b6960);
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  text-decoration-skip-ink: none; /* keep the line crisp through the digits */
  font-weight: 500;
  font-style: italic;
  letter-spacing: 0.01em;
  /* Tabular nums so the prices align column-wise across the grid. */
  font-variant-numeric: tabular-nums;
}
.live-price.on-sale .price-now {
  font-variant-numeric: tabular-nums;
  /* Make the live price feel like the answer — bold, slightly larger than
     surrounding context. The wrapper already sets 1.8rem; we lift +0.05em. */
  letter-spacing: -0.005em;
}
/* Override the 0.75em from sale-conversion to get column-stable was-prices. */
.live-product .live-price.on-sale .price-was {
  font-size: 0.78em;
}

/* The sale-pct-off pill — keep the orange but ensure the contrast on dark
   mode banners stays >= 4.5:1. */
:root[data-theme="dark"] .sale-pct-off {
  background: #d36843; /* slightly lifted orange so AA holds on dark cards */
  color: #faf9f5;
}


/* ─── 6. BUY BUTTON: idle / hover / active / focus parity in BOTH modes ──────
   The pre-existing .buy.primary / .buy.secondary live in style.css. They have
   hover but NO distinguishable :active or :focus-visible state in dark mode,
   which fails WCAG 2.4.7 on dark themes. We add states that are visible in
   BOTH modes without overriding the brand orange.
   ============================================================================= */

/* Subtle elevation on idle so the primary button always looks "pressable". */
.live-product .buy.primary,
.hero-action.primary {
  /* CSS variable shadow lets us flip it on dark mode easily. */
  box-shadow: 0 1px 0 rgba(168, 79, 49, 0.35), 0 6px 14px rgba(201, 97, 63, 0.20);
  transition:
    background-color 0.16s cubic-bezier(0.2, 0, 0, 1),
    box-shadow 0.16s cubic-bezier(0.2, 0, 0, 1),
    transform 0.06s cubic-bezier(0.2, 0, 0, 1);
}
.live-product .buy.primary:hover,
.hero-action.primary:hover {
  /* Hover lifts the shadow further. Color shift is already handled. */
  box-shadow: 0 1px 0 rgba(168, 79, 49, 0.45), 0 10px 22px rgba(201, 97, 63, 0.30);
  transform: translateY(-1px);
}
.live-product .buy.primary:active,
.hero-action.primary:active {
  /* Pressed feedback — flatten shadow, push 1px down. Distinct from idle. */
  box-shadow: 0 1px 0 rgba(168, 79, 49, 0.30), 0 2px 4px rgba(201, 97, 63, 0.18);
  transform: translateY(1px);
}
/* :focus-visible already handled by sale-conversion.css with a 2px ring;
   we layer a halo so it's visible against either ground. */
.live-product .buy.primary:focus-visible,
.hero-action.primary:focus-visible {
  box-shadow:
    0 0 0 3px rgba(250, 249, 245, 1),
    0 0 0 6px rgba(201, 97, 63, 0.55),
    0 1px 0 rgba(168, 79, 49, 0.45),
    0 8px 18px rgba(201, 97, 63, 0.25);
}
:root[data-theme="dark"] .live-product .buy.primary:focus-visible,
:root[data-theme="dark"] .hero-action.primary:focus-visible {
  box-shadow:
    0 0 0 3px rgba(15, 13, 10, 1),
    0 0 0 6px rgba(240, 129, 96, 0.65),
    0 1px 0 rgba(168, 79, 49, 0.45),
    0 8px 18px rgba(201, 97, 63, 0.30);
}

/* Secondary "Read sample first" / "Payhip mirror" — the existing rule paints
   it navy with white text, which on the cream ground is high contrast but in
   dark mode the navy nearly disappears. Lift the background and outline. */
:root[data-theme="dark"] .live-product .buy.secondary {
  background: transparent;
  color: #f0e9dc !important;
  outline: 1px solid rgba(240, 233, 220, 0.3);
  outline-offset: -1px;
}
:root[data-theme="dark"] .live-product .buy.secondary:hover {
  background: rgba(240, 233, 220, 0.06);
  outline-color: rgba(201, 97, 63, 0.55);
}


/* ─── 7. PER-KIT TRUST MICROCOPY LINE ─────────────────────────────────────────
   Each card now ends with a quiet line: "Gumroad-secured · refund any time
   · instant PDF". This is the conversion-research move — the trust signal sits
   under the CTA, not in a footer. 12.5px Inter, muted, calm dot dividers.
   ============================================================================= */
.kit-trust-line {
  margin: 4px 0 0;
  font-family: var(--sans, 'Inter', system-ui, sans-serif);
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--muted, #6b6960);
  letter-spacing: 0.01em;
}
:root[data-theme="dark"] .kit-trust-line {
  color: #c8c0b0;
}


/* ─── 8. INTERSECTIONOBSERVER-FRIENDLY STAGGER REVEAL ─────────────────────────
   Cards slide up gently as they enter the viewport. We use only CSS, with
   `animation-delay` keyed off `nth-child` so the cascade gives the row a
   pleasant rhythm without being scroll-jacky. The animation is under 280ms
   and translates < 8px so it's impeccable, not theatrical.
   We respect `prefers-reduced-motion` further down (section 13).
   ============================================================================= */
@keyframes dr-buy-card-rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.live-product-grid > .live-product {
  animation: dr-buy-card-rise 0.36s cubic-bezier(0.2, 0, 0, 1) both;
  /* `both` so the from-state holds before delay starts (prevents flash). */
}
.live-product-grid > .live-product:nth-child(1) { animation-delay: 0.00s; }
.live-product-grid > .live-product:nth-child(2) { animation-delay: 0.06s; }
.live-product-grid > .live-product:nth-child(3) { animation-delay: 0.12s; }
.live-product-grid > .live-product:nth-child(4) { animation-delay: 0.18s; }
.live-product-grid > .live-product:nth-child(5) { animation-delay: 0.24s; }
.live-product-grid > .live-product:nth-child(6) { animation-delay: 0.30s; }


/* ─── 9. FOCUS-ORDER TIGHTENING ───────────────────────────────────────────────
   When the user tabs through the page, the natural order is: skip-link → nav
   → hero CTAs → guarantee bar → kit-grid (each card's CTA in row order). We
   make sure the buy button is the first focusable child of each card by
   keeping the meta/heading/description as plain text (no <a>) and elevating
   the .buy.primary visually so it reads as the primary tab stop.
   No tabindex hack — we just enforce that nothing inside the article steals
   focus before the CTA.
   ============================================================================= */
.live-product *:focus-visible {
  /* When focusing the card itself or its descendants, give it a clean outline
     that doesn't stack with the box-shadow halo. */
  outline-offset: 2px;
}
/* If an outer hover state lifts the card, prevent the lift from affecting the
   focus halo position by anchoring on the card. */
.live-product:focus-within {
  outline: 2px solid rgba(201, 97, 63, 0.55);
  outline-offset: 4px;
  border-radius: 2px;
}


/* ─── 10. STICKY CTA NON-COLLISION RULE ───────────────────────────────────────
   The site has a sticky buy pill at bottom-right and a language switcher at
   bottom-right (already shifted via media query). On the buy page we ensure
   the floor of the page leaves room for both, and that the kit-grid never
   ends with a CTA hidden behind the sticky pill at small widths.
   ============================================================================= */
@media (max-width: 760px) {
  /* Reserve a safe area below the kit-grid so the last buy button isn't
     covered by the sticky pill or the language switcher. */
  #all-live-kits {
    padding-bottom: calc(env(safe-area-inset-bottom, 0) + 96px);
  }
  /* Live fineprint should follow the safe-area too. */
  .live-fineprint {
    padding-bottom: 8px;
  }
}


/* ─── 11. CARD-GRID ALIGNMENT (320/375/414/640/768/1024/1440) ─────────────────
   The pre-existing rule: 2 columns desktop, 1 column ≤760px. We add precise
   breakpoints so 5 cards never leave an awkward orphan, and 1024+ gets a
   3-column layout that better fills wide displays.
   At 320 (smallest supported) — strict 1 column with tighter padding so the
   buy button never wraps to two lines.
   ============================================================================= */

/* 320–414: tighten internal card padding so primary CTA fits one line. */
@media (max-width: 414px) {
  .live-product {
    padding: 22px 18px;
  }
  .live-product .buy.primary,
  .live-product .buy.secondary {
    /* Full-width CTAs on small phones so they're easy to thumb-tap. */
    display: block;
    text-align: center;
    width: 100%;
    padding: 14px 18px;
  }
  .live-product .buy-actions {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
  }
}

/* 415–760: keep existing 1-column but raise tap-targets to 44px min height. */
@media (min-width: 415px) and (max-width: 760px) {
  .live-product .buy.primary,
  .live-product .buy.secondary {
    min-height: 44px;
    line-height: 1.3;
  }
}

/* 1024+: shift to 3-column grid so 5 cards become 3 + 2 (featured first). */
@media (min-width: 1024px) {
  .live-product-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 22px;
  }
  /* Featured card spans the full first row's first cell, but if we want the
     "fastest first buy" + "most useful first buy" to lead the row, we let
     them sit in the first two columns naturally. */
}

/* 1440+: cap the grid width so cards don't stretch into unreadable widths. */
@media (min-width: 1440px) {
  .live-product-grid {
    max-width: 1240px;
    margin-left: auto;
    margin-right: auto;
  }
}


/* ─── 12. DARK-MODE PARITY for every new element ──────────────────────────────
   Each new piece (banner price spans, hero trust-line, kit trust-line, card
   ring, primary button focus halo) must look correct on both grounds. We've
   already wired most of them inline; this section catches the rest.
   ============================================================================= */
:root[data-theme="dark"] .live-product {
  background: #1a1714; /* matches --ds-surface */
  border-color: rgba(240, 233, 220, 0.12);
  box-shadow:
    0 1px 0 rgba(0, 0, 0, 0.22),
    0 10px 26px rgba(0, 0, 0, 0.32);
}
:root[data-theme="dark"] .live-product:hover,
:root[data-theme="dark"] .live-product:focus-within {
  border-color: rgba(240, 129, 96, 0.55);
  box-shadow:
    0 1px 0 rgba(0, 0, 0, 0.22),
    0 14px 30px rgba(240, 129, 96, 0.12),
    0 22px 56px rgba(0, 0, 0, 0.36);
}
:root[data-theme="dark"] .live-product.featured {
  border-color: rgba(240, 129, 96, 0.7);
}
:root[data-theme="dark"] .live-product p {
  color: #c8c0b0;
}
:root[data-theme="dark"] .live-price.on-sale s.price-was,
:root[data-theme="dark"] .live-price.on-sale .price-was {
  color: #9c948a;
}


/* ─── 13. REDUCED-MOTION FALLBACK ─────────────────────────────────────────────
   ADHD readers, vestibular sensitivities, and many users on mobile have
   reduce-motion on. Cancel the rise animation, the card-lift transforms, and
   the button-press translation. Keep colour and shadow transitions because
   they communicate state without inducing motion.
   ============================================================================= */
@media (prefers-reduced-motion: reduce) {
  .live-product-grid > .live-product {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .live-product:hover,
  .live-product:focus-within {
    transform: none !important;
  }
  .live-product .buy.primary:hover,
  .live-product .buy.primary:active,
  .hero-action.primary:hover,
  .hero-action.primary:active {
    transform: none !important;
  }
}


/* ─── 14. PRINT: hide CTAs cleanly ────────────────────────────────────────────
   If a buyer prints the page (yes, ADHD readers print things), strip the
   sticky pill, banner, language switcher, and primary CTAs — keep the prices,
   trust-lines, and refund language so the printed page reads as a receipt
   for what they're getting.
   ============================================================================= */
@media print {
  .deskrune-sale-banner,
  .deskrune-lang-switcher,
  .deskrune-proof-toast,
  .live-product .buy.secondary,
  .live-product .buy.primary {
    display: none !important;
  }
  .live-product {
    box-shadow: none !important;
    border: 0.5px solid #999 !important;
    page-break-inside: avoid;
  }
  .kit-trust-line { color: #333 !important; }
}
