/* ============================================================================
   Kindling — visual enhancements (additive). Layered on top of the existing
   site CSS; touches no existing markup or copy. Delete fx.css + fx.js (and the
   two tags in index.html) to fully revert.
   Palette reuses the site's tokens: --amber, --amber-deep, --amber-glow,
   --cream, --cream-mid, --cream-dark, --charcoal, --warm-light, --parchment.
   ============================================================================ */

/* Respect reduced-motion: kill every transition/animation this file adds. */
@media (prefers-reduced-motion: reduce) {
  .fx-reveal, .fx-tilt, .fx-vignette, .fx-parallax,
  .fx-reveal *, .fx-vignette *,
  .how-steps, .how-step, .step-num, .step-title, .step-desc,
  .note-timeline, .note-step, .note-step-num, .note-step-title, .note-step-desc,
  #pricing .pricing-card, #pricing .pricing-card *,
  .testimonials-grid, .testimonial-card, .testimonial-card * {
    animation: none !important;
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
  }
  /* fx.js never injects the vignette under reduced motion anyway, but be safe */
  .fx-vignette-wrap { display: none !important; }
  .how-steps .step-num::before, .note-timeline .note-step::after,
  #pricing .pricing-card::before { display: none !important; }
  .how-steps::before, .note-step-num, .pricing-divider { clip-path: none !important; }
  /* keep intentional, non-animation transforms (badge centering, featured scale) */
  #pricing .pricing-badge { transform: translateX(-50%) !important; }
  #pricing .pricing-card.featured { transform: scale(1.02) !important; }
}

/* ── Page-load entrance ─────────────────────────────────────────────────── */
html.fx-ready body { animation: fxBodyIn 1.1s ease-out both; }
@keyframes fxBodyIn { from { opacity: 0; } to { opacity: 1; } }

/* ── Scroll-reveal: sections & cards drift up + fade as they enter view ──── */
.fx-reveal {
  opacity: 0;
  transform: translate3d(0, 30px, 0);
  transition: opacity 1.2s cubic-bezier(.2,.7,.2,1), transform 1.2s cubic-bezier(.2,.7,.2,1);
  will-change: opacity, transform;
}
.fx-reveal.fx-in { opacity: 1; transform: translate3d(0, 0, 0); }
/* staggered children (cards within a grid) */
.fx-reveal[data-fx-delay="1"] { transition-delay: .08s; }
.fx-reveal[data-fx-delay="2"] { transition-delay: .16s; }
.fx-reveal[data-fx-delay="3"] { transition-delay: .24s; }

/* ── Tactile 3D tilt on cards (hover) ───────────────────────────────────── */
.fx-tilt {
  transform-style: preserve-3d;
  transition: transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s ease;
  transform:
    perspective(900px)
    rotateX(var(--fx-rx, 0deg))
    rotateY(var(--fx-ry, 0deg))
    translateZ(0);
}
.fx-tilt.fx-tilt-active {
  box-shadow: 0 22px 50px -18px rgba(90, 60, 10, 0.28), 0 4px 14px rgba(90,60,10,0.10);
}
/* a faint sheen that follows the cursor across tilted cards */
.fx-tilt::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    420px circle at var(--fx-mx, 50%) var(--fx-my, 0%),
    rgba(255, 250, 235, 0.35), rgba(255,250,235,0) 60%);
  opacity: 0;
  transition: opacity .25s ease;
  pointer-events: none;
}
.fx-tilt.fx-tilt-active::after { opacity: 1; }

/* ── Hero: depth + parallax + ambient light orbs ────────────────────────── */
.hero { position: relative; overflow: hidden; perspective: 1200px; }

/* nudge the existing decorative bg layers on scroll (vars set by fx.js) */
.hero .hero-bg-flame { transform: translate3d(0, var(--fx-pf, 0px), 0) scale(1.05); will-change: transform; }
.hero .hero-bg-lines { transform: translate3d(0, var(--fx-pl, 0px), 0); will-change: transform; }
.hero .hero-inner { transform: translate3d(0, var(--fx-pi, 0px), 0); }

/* a warm wash of light from the top of the hero (the "candle glow") */
.hero::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(ellipse 70% 55% at 50% -8%, rgba(245,185,68,.22), transparent 62%),
    radial-gradient(ellipse 40% 60% at 78% 50%, rgba(232,150,15,.10), transparent 70%);
}
.hero .hero-inner { position: relative; z-index: 2; }

/* the existing 🕯 emoji gets a gentle flicker/float */
.hero .hero-flame {
  display: inline-block;
  transform-origin: 50% 100%;
  animation: fxFlicker 3.4s ease-in-out infinite;
  filter: drop-shadow(0 0 14px rgba(245,185,68,.55));
}
@keyframes fxFlicker {
  0%,100% { transform: translateY(0) rotate(-1deg) scale(1); filter: drop-shadow(0 0 12px rgba(245,185,68,.45)); }
  25%     { transform: translateY(-3px) rotate(1.5deg) scale(1.04); filter: drop-shadow(0 0 18px rgba(245,185,68,.7)); }
  50%     { transform: translateY(-1px) rotate(-1.5deg) scale(0.99); filter: drop-shadow(0 0 10px rgba(245,185,68,.4)); }
  75%     { transform: translateY(-4px) rotate(0.5deg) scale(1.05); filter: drop-shadow(0 0 20px rgba(245,185,68,.75)); }
}

/* ── The hero centrepiece: an inline-SVG "the journey" vignette ────────────
   A letter travels from a house ("you") to a heart ("them") along a drawn
   route; on arrival the heart warms and a soft ring pulses. Markup injected
   by fx.js (which also adds .fx-play, only when motion is allowed). Replaces
   the old faux-3D .fx-envelope. */
.fx-vignette-wrap {
  position: absolute;
  right: 3%;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;            /* above .fx-hero-bg (z 0); the headline (.hero-inner z 2) still wins */
  pointer-events: none;
}
@media (max-width: 1220px) { .fx-vignette-wrap { display: none; } }
/* a little asymmetric room: nudge the centred headline left when the vignette shows */
@media (min-width: 1221px) {
  .hero .hero-inner { transform: translate3d(-44px, var(--fx-pi, 0px), 0); }
}
.fx-vignette { width: clamp(200px, 19vw, 300px); height: auto; display: block; }

.hv-route { fill: none; stroke: #BA7517; stroke-width: 2.4; stroke-linecap: round;
  stroke-dasharray: 100; stroke-dashoffset: 100; opacity: .72; }
.hv-house, .hv-heart { opacity: 0; }
.hv-heart { transform-origin: 248px 84px; }
.hv-pulse-1, .hv-pulse-2 { opacity: 0; transform-origin: 248px 84px; }
.hv-glow { opacity: .5; transform-origin: 160px 140px; }
/* the traveling envelope follows this path — keep it identical to <path class="hv-route"> in the injected SVG */
.hv-pkg { offset-path: path("M 40 220 C 84 146 126 254 168 176 S 216 92 248 94"); offset-rotate: auto; offset-distance: 0%; opacity: 0; }

.fx-vignette.fx-play { animation: hvReset 5.5s linear infinite; }
.fx-vignette.fx-play .hv-route   { animation: hvDrawRoute 5.5s linear infinite; }
.fx-vignette.fx-play .hv-house   { animation: hvFadeIcon  5.5s ease-out infinite; }
.fx-vignette.fx-play .hv-window  { animation: hvWindow    5.5s ease-in-out infinite; }
.fx-vignette.fx-play .hv-heart   { animation: hvHeart     5.5s ease-out infinite; }
.fx-vignette.fx-play .hv-pkg     { animation: hvTravel    5.5s cubic-bezier(.45,0,.25,1) infinite; }
.fx-vignette.fx-play .hv-pulse-1 { animation: hvPulse1    5.5s ease-out infinite; }
.fx-vignette.fx-play .hv-pulse-2 { animation: hvPulse2    5.5s ease-out infinite; }
.fx-vignette.fx-play .hv-glow    { animation: hvBreathe   5.5s ease-in-out infinite; }

/* whole-vignette: fade IN 0-3%, hold, fade OUT 95-100% so the reverse-snaps hide */
@keyframes hvReset{ 0%{opacity:0} 3%{opacity:1} 95%{opacity:1} 100%{opacity:0} }
@keyframes hvDrawRoute{ 0%,6%{stroke-dashoffset:100} 36%,95%{stroke-dashoffset:0} 100%{stroke-dashoffset:100} }
@keyframes hvFadeIcon{ 0%{opacity:0} 12%,95%{opacity:1} 100%{opacity:0} }
@keyframes hvWindow{ 0%,30%{fill:rgba(245,185,68,.55)} 40%{fill:rgba(245,185,68,1)} 60%,100%{fill:rgba(245,185,68,.75)} }
@keyframes hvHeart{ 0%{opacity:0;transform:scale(1)} 12%{opacity:1} 80%{transform:scale(1);filter:none} 88%{transform:scale(1.2);filter:drop-shadow(0 0 10px rgba(245,185,68,.7))} 95%{transform:scale(1.04);filter:drop-shadow(0 0 4px rgba(245,185,68,.3))} 100%{opacity:0;transform:scale(1)} }
@keyframes hvTravel{ 0%,34%{offset-distance:0%;opacity:0} 38%{opacity:1} 84%{offset-distance:100%;opacity:1} 88%{offset-distance:100%;opacity:0} 95%{offset-distance:100%;opacity:0} 100%{offset-distance:0%;opacity:0} }
@keyframes hvPulse1{ 0%,82%{opacity:0;transform:scale(.4)} 86%{opacity:.65} 95%{opacity:0;transform:scale(2.3)} 100%{opacity:0;transform:scale(.4)} }
@keyframes hvPulse2{ 0%,86%{opacity:0;transform:scale(.4)} 90%{opacity:.45} 96%{opacity:0;transform:scale(2)} 100%{opacity:0;transform:scale(.4)} }
@keyframes hvBreathe{ 0%,100%{opacity:.42;transform:scale(.97)} 50%{opacity:.58;transform:scale(1)} }

/* static end-state (no .fx-play) — the "before JS / JS-disabled" fallback */
.fx-vignette:not(.fx-play) .hv-route { stroke-dashoffset: 0; }
.fx-vignette:not(.fx-play) .hv-house,
.fx-vignette:not(.fx-play) .hv-heart { opacity: 1; }
.fx-vignette:not(.fx-play) .hv-heart { transform: scale(1); filter: none; }
.fx-vignette:not(.fx-play) .hv-window { fill: rgba(245,185,68,.8); }
.fx-vignette:not(.fx-play) .hv-pkg   { opacity: 0; }
.fx-vignette:not(.fx-play) .hv-glow  { opacity: .5; transform: scale(1); }

/* ── Button micro-interactions (enhance, don't replace) ─────────────────────
   A slow, faint sheen crosses the CTA on hover-IN only, then snaps back
   instantly on mouse-out (no reverse-sweep "blink"). It's a thin, low-opacity
   highlight band — the button label stays fully visible the whole time. */
.btn-primary, .nav-cta { position: relative; overflow: hidden; }
.btn-primary::after, .nav-cta::after {
  content: ""; position: absolute; top: 0; left: -130%;
  width: 55%; height: 100%;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.20), transparent);
  transform: skewX(-18deg);
  transition: none;
  pointer-events: none;
}
.btn-primary:hover::after, .nav-cta:hover::after { left: 130%; transition: left .85s ease; }
.btn-primary:active { transform: translateY(0) scale(.99); }

/* eased colour / lift on the CTAs so the hover glides in instead of snapping */
.nav-cta   { transition: background .3s ease, transform .3s ease !important; }
.btn-primary { transition: background .3s ease, box-shadow .3s ease, transform .3s ease !important; }

/* gentle lift on the existing story / theme cards even without tilt */
.theme-card, .testimonial-card, .pricing-card {
  transition: transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s ease;
}
.theme-card:hover, .testimonial-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 36px -14px rgba(90,60,10,.22);
}

/* scroll-progress filament across the very top of the page */
.fx-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 0%;
  background: linear-gradient(90deg, var(--amber-glow,#F5B944), var(--amber,#BA7517), var(--amber-deep,#7A4A08));
  z-index: 9999;
  box-shadow: 0 0 10px rgba(245,185,68,.5);
  transition: width .12s linear;
}

/* ── "Four simple steps" timeline — each step reveals ONE BY ONE ─────────── */
.how-steps .step-num { position: relative; }
/* before the choreography: whole steps hidden, line not drawn */
.how-steps:not(.fx-how-go) .how-step { opacity: 0; transform: translateY(30px); }
.how-steps:not(.fx-how-go)::before { clip-path: inset(0 100% 0 0); }

/* line draws across as the steps land */
.how-steps.fx-how-go::before { animation: fxLineDraw 1.7s cubic-bezier(.2,.7,.2,1) .1s both; }
@keyframes fxLineDraw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* STEP 1 → 4: each whole block fades + rises, ~0.45s apart so it reads "one... two... three... four" */
.how-steps.fx-how-go .how-step:nth-child(1) { animation: fxStepIn .6s cubic-bezier(.2,.7,.2,1) .15s both; }
.how-steps.fx-how-go .how-step:nth-child(2) { animation: fxStepIn .6s cubic-bezier(.2,.7,.2,1) .60s both; }
.how-steps.fx-how-go .how-step:nth-child(3) { animation: fxStepIn .6s cubic-bezier(.2,.7,.2,1) 1.05s both; }
.how-steps.fx-how-go .how-step:nth-child(4) { animation: fxStepIn .6s cubic-bezier(.2,.7,.2,1) 1.50s both; }
@keyframes fxStepIn { from { opacity:0; transform: translateY(30px); } to { opacity:1; transform: translateY(0); } }

/* the circle pops with a bounce just after its block starts */
.how-steps.fx-how-go .how-step:nth-child(1) .step-num { animation: fxStepPop .5s cubic-bezier(.34,1.56,.64,1) .30s both; }
.how-steps.fx-how-go .how-step:nth-child(2) .step-num { animation: fxStepPop .5s cubic-bezier(.34,1.56,.64,1) .75s both; }
.how-steps.fx-how-go .how-step:nth-child(3) .step-num { animation: fxStepPop .5s cubic-bezier(.34,1.56,.64,1) 1.20s both; }
.how-steps.fx-how-go .how-step:nth-child(4) .step-num { animation: fxStepPop .5s cubic-bezier(.34,1.56,.64,1) 1.65s both; }
@keyframes fxStepPop { 0% { transform: scale(.4); } 55% { transform: scale(1.16); } 100% { transform: scale(1); } }

/* an amber ring expands outward as each circle lands */
.how-steps.fx-how-go .step-num::before {
  content: ""; position: absolute; inset: -8px; border-radius: 50%;
  border: 2px solid var(--amber-glow, #F5B944); opacity: 0;
}
.how-steps.fx-how-go .how-step:nth-child(1) .step-num::before { animation: fxStepRing .8s ease-out .42s both; }
.how-steps.fx-how-go .how-step:nth-child(2) .step-num::before { animation: fxStepRing .8s ease-out .87s both; }
.how-steps.fx-how-go .how-step:nth-child(3) .step-num::before { animation: fxStepRing .8s ease-out 1.32s both; }
.how-steps.fx-how-go .how-step:nth-child(4) .step-num::before { animation: fxStepRing .8s ease-out 1.77s both; }
@keyframes fxStepRing { 0% { opacity:.75; transform: scale(.6); } 100% { opacity:0; transform: scale(1.65); } }

/* ── "Your words on their letter" cards — each one "settles onto the desk" ──
   Different metaphor from the steps timeline: the cards arrive tilted back in
   3D (as if lifting toward you), then lay flat into place one by one with a
   soft settle, their amber border briefly igniting as they land, and the big
   01/02/03 number doing a typewriter-style left-to-right wipe-in. */
.note-timeline { perspective: 1200px; }
.note-timeline .note-step { transform-style: preserve-3d; position: relative; }

.note-timeline:not(.fx-note-go) .note-step {
  opacity: 0;
  transform: rotateX(26deg) translateY(46px) scale(.9);
}
.note-timeline:not(.fx-note-go) .note-step-num { opacity: 0; clip-path: inset(0 100% 0 0); }

.note-timeline.fx-note-go .note-step:nth-child(1) { animation: fxCardSettle .8s cubic-bezier(.18,.85,.3,1) .15s both; }
.note-timeline.fx-note-go .note-step:nth-child(2) { animation: fxCardSettle .8s cubic-bezier(.18,.85,.3,1) .62s both; }
.note-timeline.fx-note-go .note-step:nth-child(3) { animation: fxCardSettle .8s cubic-bezier(.18,.85,.3,1) 1.09s both; }
@keyframes fxCardSettle {
  0%   { opacity: 0; transform: rotateX(26deg) translateY(46px) scale(.9); }
  60%  { opacity: 1; transform: rotateX(-4deg) translateY(-6px) scale(1.01); }
  100% { opacity: 1; transform: rotateX(0deg) translateY(0) scale(1); }
}

/* a warm border-glow that flashes once as the card lands */
.note-timeline.fx-note-go .note-step::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit;
  box-shadow: 0 0 0 1px var(--amber-glow, #F5B944), 0 0 30px rgba(245,185,68,.45);
  opacity: 0; pointer-events: none;
}
.note-timeline.fx-note-go .note-step:nth-child(1)::after { animation: fxCardGlow .9s ease-out .55s both; }
.note-timeline.fx-note-go .note-step:nth-child(2)::after { animation: fxCardGlow .9s ease-out 1.02s both; }
.note-timeline.fx-note-go .note-step:nth-child(3)::after { animation: fxCardGlow .9s ease-out 1.49s both; }
@keyframes fxCardGlow { 0% { opacity: 0; } 30% { opacity: .9; } 100% { opacity: 0; } }

/* the 01/02/03 number wipes in left→right like it's being typed */
.note-timeline.fx-note-go .note-step:nth-child(1) .note-step-num { animation: fxNumType .7s steps(14, end) .45s both; }
.note-timeline.fx-note-go .note-step:nth-child(2) .note-step-num { animation: fxNumType .7s steps(14, end) .92s both; }
.note-timeline.fx-note-go .note-step:nth-child(3) .note-step-num { animation: fxNumType .7s steps(14, end) 1.39s both; }
@keyframes fxNumType {
  0%   { opacity: 1; clip-path: inset(0 100% 0 0); }
  100% { opacity: 1; clip-path: inset(0 0 0 0); }
}

/* ── Pricing card — a premium, choreographed entrance ───────────────────── */
#pricing .pricing-card { position: relative; }
#pricing .pricing-card:not(.fx-price-go) { opacity: 0; }
#pricing .pricing-card:not(.fx-price-go) .pricing-badge { opacity: 0; transform: translateX(-50%) translateY(-14px) scale(.85); }
#pricing .pricing-card:not(.fx-price-go) .pricing-plan,
#pricing .pricing-card:not(.fx-price-go) .pricing-period,
#pricing .pricing-card:not(.fx-price-go) .btn-primary,
#pricing .pricing-card:not(.fx-price-go) > p:last-child { opacity: 0; }
#pricing .pricing-card:not(.fx-price-go) .pricing-price { opacity: 0; transform: scale(.5); }
#pricing .pricing-card:not(.fx-price-go) .pricing-divider { clip-path: inset(0 100% 0 0); }
#pricing .pricing-card:not(.fx-price-go) .pricing-features li { opacity: 0; transform: translateX(-12px); }

#pricing .pricing-card.fx-price-go { animation: fxFade .5s ease-out both; }
@keyframes fxFade { from { opacity: 0; } to { opacity: 1; } }

#pricing .pricing-card.fx-price-go .pricing-badge { animation: fxBadgeDrop .6s cubic-bezier(.25,.9,.3,1) .2s both; }
@keyframes fxBadgeDrop {
  0%   { opacity: 0; transform: translateX(-50%) translateY(-10px) scale(.92); }
  100% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}
#pricing .pricing-card.fx-price-go .pricing-plan { animation: fxFadeUp2 .5s ease-out .30s both; }
#pricing .pricing-card.fx-price-go .pricing-price { animation: fxPricePop .65s cubic-bezier(.34,1.6,.64,1) .42s both; }
@keyframes fxPricePop { 0% { opacity:0; transform: scale(.5); } 55% { opacity:1; transform: scale(1.14); } 100% { opacity:1; transform: scale(1); } }
#pricing .pricing-card.fx-price-go .pricing-period { animation: fxFadeUp2 .5s ease-out .60s both; }
#pricing .pricing-card.fx-price-go .pricing-divider { animation: fxDividerDraw .7s cubic-bezier(.2,.7,.2,1) .72s both; }
@keyframes fxDividerDraw { 0% { clip-path: inset(0 100% 0 0); } 100% { clip-path: inset(0 0 0 0); } }
#pricing .pricing-card.fx-price-go .pricing-features li:nth-child(1) { animation: fxLiIn .45s ease-out .90s both; }
#pricing .pricing-card.fx-price-go .pricing-features li:nth-child(2) { animation: fxLiIn .45s ease-out .98s both; }
#pricing .pricing-card.fx-price-go .pricing-features li:nth-child(3) { animation: fxLiIn .45s ease-out 1.06s both; }
#pricing .pricing-card.fx-price-go .pricing-features li:nth-child(4) { animation: fxLiIn .45s ease-out 1.14s both; }
#pricing .pricing-card.fx-price-go .pricing-features li:nth-child(5) { animation: fxLiIn .45s ease-out 1.22s both; }
#pricing .pricing-card.fx-price-go .pricing-features li:nth-child(6) { animation: fxLiIn .45s ease-out 1.30s both; }
#pricing .pricing-card.fx-price-go .pricing-features li:nth-child(7) { animation: fxLiIn .45s ease-out 1.38s both; }
@keyframes fxLiIn { 0% { opacity:0; transform: translateX(-12px); } 100% { opacity:1; transform: translateX(0); } }
#pricing .pricing-card.fx-price-go .btn-primary { animation: fxCtaIn .55s cubic-bezier(.34,1.4,.64,1) 1.5s both; }
@keyframes fxCtaIn { 0% { opacity:0; transform: translateY(12px); } 70% { opacity:1; transform: translateY(-2px); } 100% { opacity:1; transform: translateY(0); } }
#pricing .pricing-card.fx-price-go > p:last-child { animation: fxFade .5s ease-out 1.65s both; }

/* ── Testimonials — cards fade in, the big quote-mark blooms, text rises ── */
.testimonials-grid:not(.fx-testi-go) .testimonial-card { opacity: 0; }
.testimonials-grid:not(.fx-testi-go) .testimonial-quote { opacity: 0; transform: scale(1.6); }
.testimonials-grid:not(.fx-testi-go) .testimonial-text,
.testimonials-grid:not(.fx-testi-go) .testimonial-author { opacity: 0; transform: translateY(14px); }

.testimonials-grid.fx-testi-go .testimonial-card:nth-child(1) { animation: fxFade .6s ease-out .10s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(2) { animation: fxFade .6s ease-out .30s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(3) { animation: fxFade .6s ease-out .50s both; }

.testimonials-grid.fx-testi-go .testimonial-card:nth-child(1) .testimonial-quote { animation: fxQuoteBloom .75s cubic-bezier(.2,.85,.3,1) .25s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(2) .testimonial-quote { animation: fxQuoteBloom .75s cubic-bezier(.2,.85,.3,1) .45s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(3) .testimonial-quote { animation: fxQuoteBloom .75s cubic-bezier(.2,.85,.3,1) .65s both; }
@keyframes fxQuoteBloom { 0% { opacity:0; transform: scale(1.6) translateY(-10px); } 60% { opacity:1; transform: scale(.92); } 100% { opacity:1; transform: scale(1); } }

.testimonials-grid.fx-testi-go .testimonial-card:nth-child(1) .testimonial-text { animation: fxFadeUp2 .55s ease-out .42s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(2) .testimonial-text { animation: fxFadeUp2 .55s ease-out .62s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(3) .testimonial-text { animation: fxFadeUp2 .55s ease-out .82s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(1) .testimonial-author { animation: fxFadeUp2 .55s ease-out .55s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(2) .testimonial-author { animation: fxFadeUp2 .55s ease-out .75s both; }
.testimonials-grid.fx-testi-go .testimonial-card:nth-child(3) .testimonial-author { animation: fxFadeUp2 .55s ease-out .95s both; }
@keyframes fxFadeUp2 { from { opacity:0; transform: translateY(14px); } to { opacity:1; transform: translateY(0); } }

/* ════════════════════════════════════════════════════════════════════════
   Round 2 polish — overrides addressing review feedback. These tune the
   original site's spacing/contrast a touch; if Toby prefers the originals,
   delete this block.
   ════════════════════════════════════════════════════════════════════════ */

/* "Four simple steps": bolder connecting line that clearly reaches all 4 circles */
.how-steps::before {
  top: 27px !important;            /* through the centre of the 56px circles */
  left: 8% !important; right: 8% !important;
  height: 2.5px !important;
  background: linear-gradient(90deg,
    transparent, var(--amber, #BA7517) 12%, var(--amber, #BA7517) 88%, transparent) !important;
  opacity: .55 !important;
}
.how-steps { justify-items: center; }      /* keep every step centred */
.how-step { text-align: center; }
/* keep the "1·2·3·4" digits dead-centre in their circles: re-assert the
   centred flex box, drop any inherited line-height / letter-spacing, force
   lining (cap-height) figures. (The earlier text-box-trim / text-box-edge /
   text-box lines were dropped — they only work in the newest Chromium.) */
.how-steps .step-num {
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  line-height: 1 !important;
  letter-spacing: normal !important;
  text-indent: 0 !important;
  font-feature-settings: "lnum" 1, "tnum" 1;
}

/* Card content stays anchored to the TOP — when a card in a row stretches to
   match a taller sibling, its content must not drift to the middle. The note
   cards go back to block flow (the others already top-align); `justify-content`
   is also normalised in case any of them is a flex column. */
.note-timeline .note-step { display: block; }
.note-timeline .note-step,
.theme-card, .testimonial-card, .what-feature, .faq-item, .how-step,
#pricing .pricing-card {
  justify-content: flex-start !important;
}

/* prevent single-word line orphans (e.g. "…sample from Chapter / 1.") */
.section-sub, .step-desc, .note-step-desc, .testimonial-text,
.what-feature .feature-text span, .pricing-features li, .faq-question, .faq-answer p {
  text-wrap: pretty;
}

/* nudge low-contrast text up so it stays legible — but NOT the filled "Give a
   Gift" CTA (its hover background is amber-deep, so darkening its text would
   make the label vanish on hover). */
.nav-links a:not(.nav-cta):hover, .nav-links a:not(.nav-cta):focus { color: var(--amber-deep) !important; }
.note-section .note-step-desc { color: rgba(255, 251, 240, 0.82) !important; }
.note-section .note-step-title { color: var(--white, #FFFEFB) !important; }

/* testimonial quote text read too light (small + italic, and the cursor sheen
   on hover washed it further) — darken it and give it a touch more weight; same
   for the "Gifted to…" line. Section headings go a notch heavier too. */
.testimonial-text { color: #3F3930 !important; font-weight: 500; }
.testimonial-author span { color: var(--warm-mid) !important; }
.section-title { font-weight: 500 !important; }
/* keep the tilt-card sheen from whitening the text under the cursor */
.fx-tilt::after {
  background: radial-gradient(420px circle at var(--fx-mx, 50%) var(--fx-my, 0%),
    rgba(255, 250, 235, .15), rgba(255, 250, 235, 0) 60%) !important;
}

/* slightly slower, smoother card-tilt return */
.fx-tilt { transition: transform .35s cubic-bezier(.2,.7,.2,1), box-shadow .35s ease; }

/* ── Hero background — a soft abstract "candlelight" composition ────────────
   Behind the headline (z-index 0): a warm glow around the candle emoji and
   faint concentric "ripples of light" radiating out FROM it (centre is set on
   the candle by fx.js → --fx-ring-x / --fx-ring-y, with a sane fallback), a
   few large organic amber blooms in the corners, a broad diagonal sweep, and
   a whisper of grain. The site's plain horizontal rules are dimmed right back. */
.fx-hero-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  background:
    /* warm glow pooled right around the candle flame */
    radial-gradient(27% 23% at var(--fx-ring-x, 50%) var(--fx-ring-y, 24%), rgba(245,185,68,.22), rgba(245,185,68,0) 62%),
    /* large organic amber "blooms" off to the sides + corners */
    radial-gradient(38% 46% at 14% 6%,  rgba(245,185,68,.20), transparent 66%),
    radial-gradient(42% 52% at 88% 90%, rgba(232,150,15,.17), transparent 68%),
    radial-gradient(34% 42% at 96% 16%, rgba(245,185,68,.12), transparent 70%),
    radial-gradient(30% 38% at 4% 80%,  rgba(186,117,23,.11), transparent 70%),
    /* one broad diagonal sweep of warmth across the middle */
    linear-gradient(115deg, transparent 30%, rgba(245,185,68,.07) 55%, transparent 78%);
}
/* concentric "ripples of light" radiating out from the candle */
.fx-hero-bg::before {
  content: ""; position: absolute; inset: 0;
  background: repeating-radial-gradient(circle at var(--fx-ring-x, 50%) var(--fx-ring-y, 24%),
    transparent 0 54px, rgba(186,117,23,.06) 54px 56px);
  -webkit-mask-image: radial-gradient(ellipse 82% 96% at var(--fx-ring-x, 50%) var(--fx-ring-y, 24%), #000 3%, transparent 76%);
          mask-image: radial-gradient(ellipse 82% 96% at var(--fx-ring-x, 50%) var(--fx-ring-y, 24%), #000 3%, transparent 76%);
}
/* a whisper of fine grain so the soft gradients don't band */
.fx-hero-bg::after {
  content: ""; position: absolute; inset: 0; opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* dim the site's own horizontal ruled lines so the ripples lead the design */
.hero .hero-bg-lines { opacity: .3 !important; }

/* ════════════════════════════════════════════════════════════════════════
   Readability / QA pass (2026-05-12). Overrides on top of everything above.
   ════════════════════════════════════════════════════════════════════════ */

/* 1. Lift low-contrast --warm-light (#9A8D7A) text on cream → --warm-mid (#5A5048).
   These all failed WCAG AA at their sizes. */
.hero-scripture,
.letter-date,
.letter-sig,
.letter-photo-placeholder,
.what-letter .letter-note em[style*="var(--warm-light)"],
.what-letter .letter-note span[style*="var(--warm-light)"] {
  color: var(--warm-mid, #5A5048) !important;
}
/* hero eyebrow: 11px amber on cream + .22em tracking reads thin — darken + weight up */
.hero-eyebrow { color: var(--amber-deep, #7A4A08) !important; font-weight: 500; }

/* 2. Calm the hero backdrop: one soft candle-glow + one faint corner bloom
   (replaces the four-bloom / ripples / heavy-grain composition). */
.fx-hero-bg {
  background:
    radial-gradient(24% 20% at var(--fx-ring-x, 50%) var(--fx-ring-y, 24%), rgba(245,185,68,.15), rgba(245,185,68,0) 64%),
    radial-gradient(40% 50% at 90% 92%, rgba(232,150,15,.10), transparent 70%) !important;
}
.fx-hero-bg::before { opacity: .7 !important; }              /* the concentric "ripples" — kept, just gentler */
.fx-hero-bg::after  { opacity: .02 !important; }    /* keep a whisper of grain (anti-banding) */
/* halve the standalone warm wash so it doesn't stack on top of the above */
.hero::after {
  background:
    radial-gradient(ellipse 70% 55% at 50% -8%, rgba(245,185,68,.11), transparent 62%),
    radial-gradient(ellipse 40% 60% at 78% 50%, rgba(232,150,15,.05), transparent 70%) !important;
}

/* 3. The bleeding-edge text-box-* step-digit hack was removed from the
   `.how-steps .step-num` rule above (only worked in newest Chromium); the
   plain flex centring there is cross-browser. Nothing to add here. */
